From 06c4f91f00ae57b7eab67bbbe435b2e1bd5ab1e8 Mon Sep 17 00:00:00 2001 From: Jake Burkholder Date: Sat, 27 Oct 2001 07:09:40 +0000 Subject: [PATCH] Implement elf_reloc. This makes klds work. Obtained from: netbsd --- sys/sparc64/include/elf.h | 56 ++++++++ sys/sparc64/sparc64/elf_machdep.c | 216 ++++++++++++++++++++++++++++-- 2 files changed, 259 insertions(+), 13 deletions(-) diff --git a/sys/sparc64/include/elf.h b/sys/sparc64/include/elf.h index 56b45aefd1c..059c4835e54 100644 --- a/sys/sparc64/include/elf.h +++ b/sys/sparc64/include/elf.h @@ -105,6 +105,62 @@ __ElfType(Hashelt); /* * Relocation types. */ +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 /* Define "machine" characteristics */ #define ELF_TARG_CLASS ELFCLASS64 diff --git a/sys/sparc64/sparc64/elf_machdep.c b/sys/sparc64/sparc64/elf_machdep.c index e159b6c3d73..3e6c79062d9 100644 --- a/sys/sparc64/sparc64/elf_machdep.c +++ b/sys/sparc64/sparc64/elf_machdep.c @@ -1,7 +1,12 @@ /*- * Copyright (c) 2001 Jake Burkholder. + * Copyright (c) 2000 Eduardo Horvath. + * Copyright (c) 1999 The NetBSD Foundation, Inc. * All rights reserved. * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -10,19 +15,27 @@ * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * - * 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. + * 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. * + * from: NetBSD: mdreloc.c,v 1.5 2001/04/25 12:24:51 kleink Exp * $FreeBSD$ */ @@ -31,9 +44,186 @@ #include #include +#include "linker_if.h" + +/* + * The following table holds for each relocation type: + * - the width in bits of the memory location the relocation + * applies to (not currently used) + * - the number of bits the relocation value must be shifted to the + * right (i.e. discard least significant bits) to fit into + * the appropriate field in the instruction word. + * - flags indicating whether + * * the relocation involves a symbol + * * the relocation is relative to the current position + * * the relocation is for a GOT entry + * * the relocation is relative to the load address + * + */ +#define _RF_S 0x80000000 /* Resolve symbol */ +#define _RF_A 0x40000000 /* Use addend */ +#define _RF_P 0x20000000 /* Location relative */ +#define _RF_G 0x10000000 /* GOT offset */ +#define _RF_B 0x08000000 /* Load address relative */ +#define _RF_U 0x04000000 /* Unaligned */ +#define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ +#define _RF_RS(s) ( (s) & 0xff) /* right shift */ +static int reloc_target_flags[] = { + 0, /* NONE */ + _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */ + _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */ + _RF_A| _RF_B|_RF_SZ(32) | _RF_RS(10), /* HI22 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 22 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 13 */ + _RF_A| _RF_B|_RF_SZ(32) | _RF_RS(0), /* LO10 */ + _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */ + _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */ + _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ + _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ + _RF_SZ(32) | _RF_RS(0), /* COPY */ + _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* GLOB_DAT */ + _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ + _RF_A| _RF_B|_RF_SZ(64) | _RF_RS(0), /* RELATIVE */ + _RF_S|_RF_A| _RF_U|_RF_SZ(32) | _RF_RS(0), /* UA_32 */ + + _RF_A| _RF_SZ(32) | _RF_RS(0), /* PLT32 */ + _RF_A| _RF_SZ(32) | _RF_RS(10), /* HIPLT22 */ + _RF_A| _RF_SZ(32) | _RF_RS(0), /* LOPLT10 */ + _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT32 */ + _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PCPLT22 */ + _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT10 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 10 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 11 */ + _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* 64 */ + _RF_S|_RF_A|/*extra*/ _RF_SZ(32) | _RF_RS(0), /* OLO10 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(42), /* HH22 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(32), /* HM10 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* LM22 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(42), /* PC_HH22 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(32), /* PC_HM10 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC_LM22 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP16 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP19 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_JMP */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 7 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 5 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 6 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(64) | _RF_RS(0), /* DISP64 */ + _RF_A| _RF_SZ(64) | _RF_RS(0), /* PLT64 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HIX22 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LOX10 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(22), /* H44 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(12), /* M44 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* L44 */ + _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* REGISTER */ + _RF_S|_RF_A| _RF_U| _RF_SZ(64) | _RF_RS(0), /* UA64 */ + _RF_S|_RF_A| _RF_U| _RF_SZ(16) | _RF_RS(0), /* UA16 */ +}; + +#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) +#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) +#define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) +#define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) +#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) +#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) +#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) + +static long reloc_target_bitmask[] = { +#define _BM(x) (~(-(1ULL << (x)))) + 0, /* NONE */ + _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */ + _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ + _BM(30), _BM(22), /* WDISP30, WDISP22 */ + _BM(22), _BM(22), /* HI22, _22 */ + _BM(13), _BM(10), /* RELOC_13, _LO10 */ + _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ + _BM(10), _BM(22), /* _PC10, _PC22 */ + _BM(30), 0, /* _WPLT30, _COPY */ + _BM(32), _BM(32), _BM(32), /* _GLOB_DAT, JMP_SLOT, _RELATIVE */ + _BM(32), _BM(32), /* _UA32, PLT32 */ + _BM(22), _BM(10), /* _HIPLT22, LOPLT10 */ + _BM(32), _BM(22), _BM(10), /* _PCPLT32, _PCPLT22, _PCPLT10 */ + _BM(10), _BM(11), -1, /* _10, _11, _64 */ + _BM(10), _BM(22), /* _OLO10, _HH22 */ + _BM(10), _BM(22), /* _HM10, _LM22 */ + _BM(22), _BM(10), _BM(22), /* _PC_HH22, _PC_HM10, _PC_LM22 */ + _BM(16), _BM(19), /* _WDISP16, _WDISP19 */ + -1, /* GLOB_JMP */ + _BM(7), _BM(5), _BM(6) /* _7, _5, _6 */ + -1, -1, /* DISP64, PLT64 */ + _BM(22), _BM(13), /* HIX22, LOX10 */ + _BM(22), _BM(10), _BM(13), /* H44, M44, L44 */ + -1, -1, _BM(16), /* REGISTER, UA64, UA16 */ +#undef _BM +}; +#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) + +/* Process one elf relocation with addend. */ int -elf_reloc(linker_file_t lf, const void *data, int type, const char *sym) +elf_reloc(linker_file_t lf, const void *data, int type, const char *symname) { - TODO; + const Elf_Rela *rela; + Elf_Addr relocbase; + Elf_Half *where32; + Elf_Addr *where; + Elf_Word rtype; + Elf_Addr value; + Elf_Addr mask; + caddr_t addr; + + if (type != ELF_RELOC_RELA) + return (-1); + + relocbase = (Elf_Addr)lf->address; + rela = (const Elf_Rela *)data; + where = (Elf_Addr *)(relocbase + rela->r_offset); + where32 = (Elf_Half *)where; + rtype = ELF_R_TYPE(rela->r_info); + + if (rtype == R_SPARC_NONE) + return (0); + + if (rtype == R_SPARC_JMP_SLOT || rtype == R_SPARC_COPY || + rtype > R_SPARC_UA16) + return (-1); + + if (RELOC_UNALIGNED(rtype)) + return (-1); + + value = rela->r_addend; + + if (RELOC_RESOLVE_SYMBOL(rtype)) { + addr = linker_file_lookup_symbol(lf, symname, 1); + if (addr == 0) + return (-1); + value += (Elf_Addr)addr; + } + + if (RELOC_PC_RELATIVE(rtype)) + value -= (Elf_Addr)where; + + if (RELOC_BASE_RELATIVE(rtype)) + value += (Elf_Addr)(relocbase); + + mask = RELOC_VALUE_BITMASK(rtype); + value >>= RELOC_VALUE_RIGHTSHIFT(rtype); + value &= mask; + + if (RELOC_TARGET_SIZE(rtype) > 32) { + *where &= ~mask; + *where |= value; + } else { + *where32 &= ~mask; + *where32 |= value; + } + return (0); }