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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2019 Joyent, Inc.
  28  */
  29 
  30 /*
  31  * While this is no longer relevant to the kernel, we keep it in its
  32  * traditional location to match the other variants, used from the ld
  33  * code.
  34  */
  35 
  36 #define ELF_TARGET_386
  37 #if defined(DO_RELOC_LIBLD)
  38 #undef DO_RELOC_LIBLD
  39 #define DO_RELOC_LIBLD_X86
  40 #endif
  41 #include        <stdio.h>
  42 #include        "sgs.h"
  43 #include        "machdep.h"
  44 #include        "libld.h"
  45 #include        "reloc.h"
  46 #include        "conv.h"
  47 #include        "msg.h"
  48 
  49 /*
  50  * We need to build this code differently when it is used for
  51  * cross linking:
  52  *      - Data alignment requirements can differ from those
  53  *              of the running system, so we can't access data
  54  *              in units larger than a byte
  55  *      - We have to include code to do byte swapping when the
  56  *              target and linker host use different byte ordering,
  57  *              but such code is a waste when running natively.
  58  */
  59 #if !defined(DO_RELOC_LIBLD) || defined(__i386) || defined(__amd64)
  60 #define DORELOC_NATIVE
  61 #endif
  62 
  63 /*
  64  * This table represents the current relocations that do_reloc() is able to
  65  * process.  The relocations below that are marked SPECIAL are relocations that
  66  * take special processing and shouldn't actually ever be passed to do_reloc().
  67  */
  68 const Rel_entry reloc_table[R_386_NUM] = {
  69 /* R_386_NONE */        {0, FLG_RE_NOTREL, 0, 0, 0},
  70 /* R_386_32 */          {0, FLG_RE_NOTREL, 4, 0, 0},
  71 /* R_386_PC32 */        {0, FLG_RE_PCREL, 4, 0, 0},
  72 /* R_386_GOT32 */       {0, FLG_RE_GOTADD, 4, 0, 0},
  73 /* R_386_PLT32 */       {0, FLG_RE_PLTREL | FLG_RE_PCREL, 4, 0, 0},
  74 /* R_386_COPY */        {0, FLG_RE_NOTREL, 0, 0, 0},            /* SPECIAL */
  75 /* R_386_GLOB_DAT */    {0, FLG_RE_NOTREL, 4, 0, 0},
  76 /* R_386_JMP_SLOT */    {0, FLG_RE_NOTREL, 4, 0, 0},            /* SPECIAL */
  77 /* R_386_RELATIVE */    {0, FLG_RE_NOTREL, 4, 0, 0},
  78 /* R_386_GOTOFF */      {0, FLG_RE_GOTREL, 4, 0, 0},
  79 /* R_386_GOTPC */       {0, FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND, 4,
  80                             0, 0},
  81 /* R_386_32PLT */       {0, FLG_RE_PLTREL, 4, 0, 0},
  82 /* R_386_TLS_GD_PLT */  {0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_TLSGD, 4,
  83                             0, 0},
  84 /* R_386_TLS_LDM_PLT */ {0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_TLSLD, 4,
  85                             0, 0},
  86 /* R_386_TLS_TPOFF */   {0, FLG_RE_NOTREL, 4, 0, 0},
  87 /* R_386_TLS_IE */      {0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 0, 0},
  88 /* R_386_TLS_GOTIE */   {0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 0, 0},
  89 /* R_386_TLS_LE */      {0, FLG_RE_TLSLE, 4, 0, 0},
  90 /* R_386_TLS_GD */      {0, FLG_RE_GOTADD | FLG_RE_TLSGD, 4, 0, 0},
  91 /* R_386_TLS_LDM */     {0, FLG_RE_GOTADD | FLG_RE_TLSLD, 4, 0, 0},
  92 /* R_386_16 */          {0, FLG_RE_NOTREL, 2, 0, 0},
  93 /* R_386_PC16 */        {0, FLG_RE_PCREL, 2, 0, 0},
  94 /* R_386_8 */           {0, FLG_RE_NOTREL, 1, 0, 0},
  95 /* R_386_PC8 */         {0, FLG_RE_PCREL, 1, 0, 0},
  96 /* R_386_UNKNOWN24 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  97 /* R_386_UNKNOWN25 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  98 /* R_386_UNKNOWN26 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  99 /* R_386_UNKNOWN27 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 100 /* R_386_UNKNOWN28 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 101 /* R_386_UNKNOWN29 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 102 /* R_386_UNKNOWN30 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 103 /* R_386_UNKNOWN31 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 104 /* R_386_TLS_LDO_32 */  {0, FLG_RE_TLSLD, 4, 0, 0},
 105 /* R_386_UNKNOWN33 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 106 /* R_386_UNKNOWN34 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 107 /* R_386_TLS_DTPMOD32 */ {0, FLG_RE_NOTREL, 4, 0, 0},
 108 /* R_386_TLS_DTPOFF32 */ {0, FLG_RE_NOTREL, 4, 0, 0},
 109 /* R_386_UNKONWN37 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 110 /* R_386_SIZE32 */      {0, FLG_RE_SIZE | FLG_RE_VERIFY, 4, 0, 0}
 111 };
 112 
 113 /*
 114  * Write a single relocated value to its reference location.
 115  * We assume we wish to add the relocation amount, value, to the
 116  * value of the address already present at the offset.
 117  *
 118  * NAME                 VALUE   FIELD           CALCULATION
 119  *
 120  * R_386_NONE            0      none            none
 121  * R_386_32              1      word32          S + A
 122  * R_386_PC32            2      word32          S + A - P
 123  * R_386_GOT32           3      word32          G + A - P
 124  * R_386_PLT32           4      word32          L + A - P
 125  * R_386_COPY            5      none            none
 126  * R_386_GLOB_DAT        6      word32          S
 127  * R_386_JMP_SLOT        7      word32          S
 128  * R_386_RELATIVE        8      word32          B + A
 129  * R_386_GOTOFF          9      word32          S + A - GOT
 130  * R_386_GOTPC          10      word32          GOT + A - P
 131  * R_386_32PLT          11      word32          L + A
 132  * R_386_TLS_GD_PLT     12      word32          @tlsgdplt
 133  * R_386_TLS_LDM_PLT    13      word32          @tlsldmplt
 134  * R_386_TLS_TPOFF      14      word32          @ntpoff(S)
 135  * R_386_TLS_IE         15      word32          @indntpoff(S)
 136  * R_386_TLS_GD         18      word32          @tlsgd(S)
 137  * R_386_TLS_LDM        19      word32          @tlsldm(S)
 138  * R_386_16             20      word16          S + A
 139  * R_386_PC16           21      word16          S + A - P
 140  * R_386_8              22      word8           S + A
 141  * R_386_PC8            23      word8           S + A - P
 142  * R_386_TLS_LDO_32     32      word32          @dtpoff(S)
 143  * R_386_TLS_DTPMOD32   35      word32          @dtpmod(S)
 144  * R_386_TLS_DTPOFF32   36      word32          @dtpoff(S)
 145  * R_386_SIZE32         38      word32          Z + A
 146  *
 147  * Relocations 0-10 are from Figure 4-4: Relocation Types from the
 148  * intel ABI.  Relocation 11 (R_386_32PLT) is from the C++ intel abi
 149  * and is in the process of being registered with intel ABI (1/13/94).
 150  *
 151  * Relocations R_386_TLS_* are added to support Thread-Local storage
 152  *      as recorded in PSARC/2001/509
 153  *
 154  * Relocation calculations:
 155  *
 156  * CALCULATION uses the following notation:
 157  *      A       the addend used
 158  *      B       the base address of the shared object in memory
 159  *      G       the offset into the global offset table
 160  *      GOT     the address of teh global offset table
 161  *      L       the procedure linkage entry
 162  *      P       the place of the storage unit being relocated
 163  *      S       the value of the symbol
 164  *      Z       the size of the symbol whose index resides in the relocation
 165  *              entry
 166  *
 167  *      @dtlndx(x): Allocate two contiguous entries in the GOT table to hold
 168  *         a Tls_index structure (for passing to __tls_get_addr()). The
 169  *         instructions referencing this entry will be bound to the first
 170  *         of the two GOT entries.
 171  *
 172  *      @tmndx(x): Allocate two contiguous entries in the GOT table to hold
 173  *         a Tls_index structure (for passing to __tls_get_addr()). The
 174  *         ti_offset field of the Tls_index will be set to 0 (zero) and the
 175  *         ti_module will be filled in at run-time. The call to
 176  *         __tls_get_addr() will return the starting offset of the dynamic
 177  *         TLS block.
 178  *
 179  *      @dtpoff(x): calculate the tlsoffset relative to the TLS block.
 180  *
 181  *      @tpoff(x): calculate the tlsoffset relative to the TLS block.
 182  *
 183  *      @dtpmod(x): calculate the module id of the object containing symbol x.
 184  *
 185  * The calculations in the CALCULATION column are assumed to have
 186  * been performed before calling this function except for the addition of
 187  * the addresses in the instructions.
 188  */
 189 #if defined(DO_RELOC_LIBLD)
 190 /*ARGSUSED5*/
 191 int
 192 do_reloc_ld(Rel_desc *rdesc, uchar_t *off, Xword *value,
 193     rel_desc_sname_func_t rel_desc_sname_func,
 194     const char *file, int bswap, void *lml)
 195 #else
 196 int
 197 do_reloc_rtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
 198     const char *file, void *lml)
 199 #endif
 200 {
 201 #ifdef DO_RELOC_LIBLD
 202 #define sym (* rel_desc_sname_func)(rdesc)
 203         uchar_t rtype = rdesc->rel_rtype;
 204 #endif
 205         const Rel_entry *rep;
 206 
 207         rep = &reloc_table[rtype];
 208 
 209         switch (rep->re_fsize) {
 210         case 1:
 211                 /* LINTED */
 212                 *((uchar_t *)off) += (uchar_t)(*value);
 213                 break;
 214 
 215         case 2:
 216 #if defined(DORELOC_NATIVE)
 217                 /* LINTED */
 218                 *((Half *)off) += (Half)(*value);
 219 #else
 220                 {
 221                         Half    v;
 222                         uchar_t *v_bytes = (uchar_t *)&v;
 223 
 224                         if (bswap) {
 225                                 UL_ASSIGN_BSWAP_HALF(v_bytes, off);
 226                                 v += *value;
 227                                 UL_ASSIGN_BSWAP_HALF(off, v_bytes);
 228                         } else {
 229                                 UL_ASSIGN_HALF(v_bytes, off);
 230                                 v += *value;
 231                                 UL_ASSIGN_HALF(off, v_bytes);
 232                         }
 233                 }
 234 #endif
 235                 break;
 236 
 237         case 4:
 238 #if defined(DORELOC_NATIVE)
 239                 /* LINTED */
 240                 *((Xword *)off) += *value;
 241 #else
 242                 {
 243                         Word    v;
 244                         uchar_t *v_bytes = (uchar_t *)&v;
 245 
 246                         if (bswap) {
 247                                 UL_ASSIGN_BSWAP_WORD(v_bytes, off);
 248                                 v += *value;
 249                                 UL_ASSIGN_BSWAP_WORD(off, v_bytes);
 250                         } else {
 251                                 UL_ASSIGN_WORD(v_bytes, off);
 252                                 v += *value;
 253                                 UL_ASSIGN_WORD(off, v_bytes);
 254                         }
 255                 }
 256 #endif
 257                 break;
 258         default:
 259                 /*
 260                  * To keep chkmsg() happy: MSG_INTL(MSG_REL_UNSUPSZ)
 261                  */
 262                 REL_ERR_UNSUPSZ(lml, file, sym, rtype, rep->re_fsize);
 263                 return (0);
 264         }
 265         return (1);
 266 
 267 #ifdef DO_RELOC_LIBLD
 268 #undef sym
 269 #endif
 270 }