1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #if defined(_KERNEL) 30 #include <sys/types.h> 31 #include "reloc.h" 32 #else 33 #include <stdio.h> 34 #include "sgs.h" 35 #include "machdep.h" 36 #include "libld.h" 37 #include "reloc.h" 38 #include "conv.h" 39 #include "msg.h" 40 #endif 41 42 /* 43 * This table represents the current relocations that do_reloc() 44 * is able to process. The relocations below that are marked 45 * 'SPECIAL' in the comments are relocations that take special 46 * processing and shouldn't actually ever be passed to do_reloc(). 47 */ 48 const Rel_entry reloc_table[R_AMD64_NUM] = { 49 /* R_AMD64_NONE */ {0, 0}, 50 /* R_AMD64_64 */ {FLG_RE_NOTREL, 8}, 51 /* R_AMD64_PC32 */ {FLG_RE_PCREL, 4}, 52 /* R_AMD64_GOT32 */ {FLG_RE_NOTSUP, 0}, 53 /* R_AMD64_PLT32 */ {FLG_RE_PCREL | FLG_RE_PLTREL | 54 FLG_RE_VERIFY | FLG_RE_SIGN, 4}, 55 /* R_AMD64_COPY */ {FLG_RE_NOTSUP, 0}, 56 /* R_AMD64_GLOB_DAT */ {FLG_RE_NOTREL, 8}, 57 /* R_AMD64_JUMP_SLOT */ {FLG_RE_NOTSUP, 0}, 58 /* R_AMD64_RELATIVE */ {FLG_RE_NOTREL, 8}, 59 /* R_AMD64_GOTPCREL */ {FLG_RE_GOTPC | FLG_RE_GOTADD, 4}, 60 /* R_AMD64_32 */ {FLG_RE_NOTREL, 4}, 61 /* R_AMD64_32S */ {FLG_RE_NOTREL, 4}, 62 /* R_AMD64_16 */ {FLG_RE_NOTSUP, 0}, 63 /* R_AMD64_PC16 */ {FLG_RE_NOTSUP, 0}, 64 /* R_AMD64_8 */ {FLG_RE_NOTSUP, 0}, 65 /* R_AMD64_PC8 */ {FLG_RE_NOTSUP, 0}, 66 /* R_AMD64_DTPMOD64 */ {FLG_RE_NOTREL, 8}, 67 /* R_AMD64_DTPOFF64 */ {FLG_RE_NOTREL, 8}, 68 /* R_AMD64_TPOFF64 */ {FLG_RE_NOTREL, 8}, 69 /* R_AMD64_TLSGD */ {FLG_RE_GOTPC | FLG_RE_GOTADD | 70 FLG_RE_TLSINS | FLG_RE_TLSGD, 4}, 71 /* R_AMD64_TLSLD */ {FLG_RE_GOTPC | FLG_RE_GOTADD | 72 FLG_RE_TLSINS | FLG_RE_TLSLD, 4}, 73 /* R_AMD64_DTPOFF32 */ {FLG_RE_TLSINS | FLG_RE_NOTREL | FLG_RE_TLSLD, 4}, 74 /* R_AMD64_GOTTPOFF */ {FLG_RE_GOTPC | FLG_RE_GOTADD | 75 FLG_RE_TLSINS | FLG_RE_TLSIE, 4}, 76 /* R_AMD64_TPOFF32 */ {FLG_RE_TLSINS | FLG_RE_NOTREL | FLG_RE_TLSLE, 4}, 77 /* R_AMD64_PC64 */ {FLG_RE_PCREL, 8}, 78 /* R_AMD64_GOTOFF64 */ {FLG_RE_GOTREL, 8}, 79 /* R_AMD64_GOTPC32 */ {FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND, 4} 80 }; 81 #if (R_AMD64_NUM != (R_AMD64_GOTPC32 + 1)) 82 #error "R_AMD64_NUM has grown" 83 #endif 84 85 /* 86 * Write a single relocated value to its reference location. 87 * We assume we wish to add the relocatoin amount, value, to the 88 * value of the address already present at the offset. 89 * 90 * NAME VALUE FIELD CALCULATION 91 * 92 * R_AMD64_NONE 0 none none 93 * R_AMD64_64 1 word64 S + A 94 * R_AMD64_PC32 2 word64 S + A 95 * R_AMD64_GOT32 3 word32 G + A 96 * R_AMD64_PLT32 4 word32 L + A - P 97 * R_AMD64_COPY 5 none none 98 * R_AMD64_GLOB_DAT 6 word64 S 99 * R_AMD64_JUMP_SLOT 7 word64 S 100 * R_AMD64_RELATIVE 8 word64 B + A 101 * R_AMD64_GOTPCREL 9 word32 G + GOT + A - P 102 * R_AMD64_32 10 word32 S + A 103 * R_AMD64_32S 11 word32 S + A 104 * R_AMD64_16 12 word16 S + A 105 * R_AMD64_PC16 13 word16 S + A - P 106 * R_AMD64_8 14 word8 S + A 107 * R_AMD64_PC8 15 word8 S + A - P 108 * R_AMD64_DTPMOD64 16 word64 109 * R_AMD64_DTPOFF64 17 word64 110 * R_AMD64_TPOFF64 18 word64 111 * R_AMD64_TLSGD 19 word32 112 * R_AMD64_TLSLD 20 word32 113 * R_AMD64_DTPOFF32 21 word32 114 * R_AMD64_GOTTPOFF 22 word32 115 * R_AMD64_TPOFF32 23 word32 116 * R_AMD64_PC64 24 word32 S + A - P 117 * R_AMD64_GOTOFF64 25 word32 S + A - GOT 118 * R_AMD64_GOTPC32 26 word32 GOT + A - P 119 * 120 * Relocation calculations: 121 * A Represents the addend used to compute the value of the 122 * relocatable field. 123 * 124 * B Represents the base address at which a shared objects has 125 * been loaded into memory during executaion. Generally, a 126 * shared objects is built with a 0 base virtual address, 127 * but the execution address will be different. 128 * 129 * G Represents the offset into the global offset table 130 * at which the relocation entry's symbol will reside 131 * during execution. 132 * 133 * GOT Rrepresents the address of the global offset table. 134 * 135 * L Represents the place (section offset or address) of 136 * the Procedure Linkage Table entry for a symbol. 137 * 138 * P Represents the place (section offset or address) of the 139 * storage unit being relocated (computed using r_offset). 140 * 141 * S Represents the value of the symbol whose index resides 142 * in the relocation entry. 143 * 144 */ 145 146 #define HIBITS 0xffffffff80000000ULL 147 148 int 149 do_reloc(unsigned char rtype, unsigned char *off, Xword *value, 150 const char *sym, const char *file) 151 { 152 const Rel_entry *rep; 153 154 rep = &reloc_table[rtype]; 155 156 if (rep->re_fsize == 4) { 157 /* 158 * The amd64 psABI requires that we perform 159 * the following verifications: 160 * 161 * The R_AMD64_32 and R_AMD64_32S relocations 162 * truncate the computed value to 32bits. The linker 163 * must verify that the generated value for the 164 * R_AMD64_32(R_AMD64_32S) relocation zero-extends 165 * (sign extends) to the original 64-bit value. 166 * 167 * Also - the following relocations are all 32 bit PC relative 168 * references, so we must validate that the value being 169 * written will fit in the field provided. 170 * 171 * R_AMD64_PC32, R_AMD64_GOTPC32, R_AMD64_GOTPCREL 172 */ 173 if (rtype == R_AMD64_32) { 174 /* 175 * We must verify that this value will 'zero-extend', 176 * this requires that the upper 33bits all be 177 * 'zero'. 178 */ 179 if ((*value & HIBITS) != 0) { 180 /* 181 * to keep chkmsg() happy: 182 * MSG_INTL(MSG_REL_NOFIT) 183 */ 184 REL_ERR_NOFIT(file, sym, rtype, *value); 185 return (0); 186 } 187 } else if ((rtype == R_AMD64_32S) || 188 (rtype == R_AMD64_PC32) || 189 (rtype == R_AMD64_GOTPCREL) || 190 (rtype == R_AMD64_GOTPC32)) { 191 /* 192 * We must verify that this value will properly 193 * sign extend. This is true of the upper 194 * 33bits are all either 'zero' or 195 * all 'one'. 196 */ 197 if (((*value & HIBITS) != HIBITS) && 198 ((*value & HIBITS) != 0)) { 199 /* 200 * to keep chkmsg() happy: 201 * MSG_INTL(MSG_REL_NOFIT) 202 */ 203 REL_ERR_NOFIT(file, sym, rtype, *value); 204 return (0); 205 } 206 } 207 /* LINTED */ 208 *((Word *)off) += *value; 209 } else if (rep->re_fsize == 8) { 210 *((Xword *)off) += *value; 211 } else { 212 eprintf(ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), 213 conv_reloc_amd64_type_str(rtype), file, 214 (sym ? sym : MSG_INTL(MSG_STR_UNKNOWN)), 215 EC_WORD(rep->re_fsize)); 216 return (0); 217 } 218 return (1); 219 } 220