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 #if     defined(_KERNEL)
  27 #include        <sys/types.h>
  28 #include        "reloc.h"
  29 #else
  30 #define ELF_TARGET_386
  31 #if defined(DO_RELOC_LIBLD)
  32 #undef DO_RELOC_LIBLD
  33 #define DO_RELOC_LIBLD_X86
  34 #endif
  35 #include        <stdio.h>
  36 #include        "sgs.h"
  37 #include        "machdep.h"
  38 #include        "libld.h"
  39 #include        "reloc.h"
  40 #include        "conv.h"
  41 #include        "msg.h"
  42 #endif
  43 
  44 /*
  45  * We need to build this code differently when it is used for
  46  * cross linking:
  47  *      - Data alignment requirements can differ from those
  48  *              of the running system, so we can't access data
  49  *              in units larger than a byte
  50  *      - We have to include code to do byte swapping when the
  51  *              target and linker host use different byte ordering,
  52  *              but such code is a waste when running natively.
  53  */
  54 #if !defined(DO_RELOC_LIBLD) || defined(__i386) || defined(__amd64)
  55 #define DORELOC_NATIVE
  56 #endif
  57 
  58 /*
  59  * This table represents the current relocations that do_reloc() is able to
  60  * process.  The relocations below that are marked SPECIAL are relocations that
  61  * take special processing and shouldn't actually ever be passed to do_reloc().
  62  */
  63 const Rel_entry reloc_table[R_386_NUM] = {
  64 /* R_386_NONE */        {0, FLG_RE_NOTREL, 0, 0, 0},
  65 /* R_386_32 */          {0, FLG_RE_NOTREL, 4, 0, 0},
  66 /* R_386_PC32 */        {0, FLG_RE_PCREL, 4, 0, 0},
  67 /* R_386_GOT32 */       {0, FLG_RE_GOTADD, 4, 0, 0},
  68 /* R_386_PLT32 */       {0, FLG_RE_PLTREL | FLG_RE_PCREL, 4, 0, 0},
  69 /* R_386_COPY */        {0, FLG_RE_NOTREL, 0, 0, 0},            /* SPECIAL */
  70 /* R_386_GLOB_DAT */    {0, FLG_RE_NOTREL, 4, 0, 0},
  71 /* R_386_JMP_SLOT */    {0, FLG_RE_NOTREL, 4, 0, 0},            /* SPECIAL */
  72 /* R_386_RELATIVE */    {0, FLG_RE_NOTREL, 4, 0, 0},
  73 /* R_386_GOTOFF */      {0, FLG_RE_GOTREL, 4, 0, 0},
  74 /* R_386_GOTPC */       {0, FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND, 4,
  75                             0, 0},
  76 /* R_386_32PLT */       {0, FLG_RE_PLTREL, 4, 0, 0},
  77 /* R_386_TLS_GD_PLT */  {0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_TLSGD, 4,
  78                             0, 0},
  79 /* R_386_TLS_LDM_PLT */ {0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_TLSLD, 4,
  80                             0, 0},
  81 /* R_386_TLS_TPOFF */   {0, FLG_RE_NOTREL, 4, 0, 0},
  82 /* R_386_TLS_IE */      {0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 0, 0},
  83 /* R_386_TLS_GOTIE */   {0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 0, 0},
  84 /* R_386_TLS_LE */      {0, FLG_RE_TLSLE, 4, 0, 0},
  85 /* R_386_TLS_GD */      {0, FLG_RE_GOTADD | FLG_RE_TLSGD, 4, 0, 0},
  86 /* R_386_TLS_LDM */     {0, FLG_RE_GOTADD | FLG_RE_TLSLD, 4, 0, 0},
  87 /* R_386_16 */          {0, FLG_RE_NOTREL, 2, 0, 0},
  88 /* R_386_PC16 */        {0, FLG_RE_PCREL, 2, 0, 0},
  89 /* R_386_8 */           {0, FLG_RE_NOTREL, 1, 0, 0},
  90 /* R_386_PC8 */         {0, FLG_RE_PCREL, 1, 0, 0},
  91 /* R_386_UNKNOWN24 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  92 /* R_386_UNKNOWN25 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  93 /* R_386_UNKNOWN26 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  94 /* R_386_UNKNOWN27 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  95 /* R_386_UNKNOWN28 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  96 /* R_386_UNKNOWN29 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  97 /* R_386_UNKNOWN30 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  98 /* R_386_UNKNOWN31 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
  99 /* R_386_TLS_LDO_32 */  {0, FLG_RE_TLSLD, 4, 0, 0},
 100 /* R_386_UNKNOWN33 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 101 /* R_386_UNKNOWN34 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 102 /* R_386_TLS_DTPMOD32 */ {0, FLG_RE_NOTREL, 4, 0, 0},
 103 /* R_386_TLS_DTPOFF32 */ {0, FLG_RE_NOTREL, 4, 0, 0},
 104 /* R_386_UNKONWN37 */   {0, FLG_RE_NOTSUP, 0, 0, 0},
 105 /* R_386_SIZE32 */      {0, FLG_RE_SIZE | FLG_RE_VERIFY, 4, 0, 0}
 106 };
 107 
 108 /*
 109  * Write a single relocated value to its reference location.
 110  * We assume we wish to add the relocation amount, value, to the
 111  * value of the address already present at the offset.
 112  *
 113  * NAME                 VALUE   FIELD           CALCULATION
 114  *
 115  * R_386_NONE            0      none            none
 116  * R_386_32              1      word32          S + A
 117  * R_386_PC32            2      word32          S + A - P
 118  * R_386_GOT32           3      word32          G + A - P
 119  * R_386_PLT32           4      word32          L + A - P
 120  * R_386_COPY            5      none            none
 121  * R_386_GLOB_DAT        6      word32          S
 122  * R_386_JMP_SLOT        7      word32          S
 123  * R_386_RELATIVE        8      word32          B + A
 124  * R_386_GOTOFF          9      word32          S + A - GOT
 125  * R_386_GOTPC          10      word32          GOT + A - P
 126  * R_386_32PLT          11      word32          L + A
 127  * R_386_TLS_GD_PLT     12      word32          @tlsgdplt
 128  * R_386_TLS_LDM_PLT    13      word32          @tlsldmplt
 129  * R_386_TLS_TPOFF      14      word32          @ntpoff(S)
 130  * R_386_TLS_IE         15      word32          @indntpoff(S)
 131  * R_386_TLS_GD         18      word32          @tlsgd(S)
 132  * R_386_TLS_LDM        19      word32          @tlsldm(S)
 133  * R_386_16             20      word16          S + A
 134  * R_386_PC16           21      word16          S + A - P
 135  * R_386_8              22      word8           S + A
 136  * R_386_PC8            23      word8           S + A - P
 137  * R_386_TLS_LDO_32     32      word32          @dtpoff(S)
 138  * R_386_TLS_DTPMOD32   35      word32          @dtpmod(S)
 139  * R_386_TLS_DTPOFF32   36      word32          @dtpoff(S)
 140  * R_386_SIZE32         38      word32          Z + A
 141  *
 142  * Relocations 0-10 are from Figure 4-4: Relocation Types from the
 143  * intel ABI.  Relocation 11 (R_386_32PLT) is from the C++ intel abi
 144  * and is in the process of being registered with intel ABI (1/13/94).
 145  *
 146  * Relocations R_386_TLS_* are added to support Thread-Local storage
 147  *      as recorded in PSARC/2001/509
 148  *
 149  * Relocation calculations:
 150  *
 151  * CALCULATION uses the following notation:
 152  *      A       the addend used
 153  *      B       the base address of the shared object in memory
 154  *      G       the offset into the global offset table
 155  *      GOT     the address of teh global offset table
 156  *      L       the procedure linkage entry
 157  *      P       the place of the storage unit being relocated
 158  *      S       the value of the symbol
 159  *      Z       the size of the symbol whose index resides in the relocation
 160  *              entry
 161  *
 162  *      @dtlndx(x): Allocate two contiguous entries in the GOT table to hold
 163  *         a Tls_index structure (for passing to __tls_get_addr()). The
 164  *         instructions referencing this entry will be bound to the first
 165  *         of the two GOT entries.
 166  *
 167  *      @tmndx(x): Allocate two contiguous entries in the GOT table to hold
 168  *         a Tls_index structure (for passing to __tls_get_addr()). The
 169  *         ti_offset field of the Tls_index will be set to 0 (zero) and the
 170  *         ti_module will be filled in at run-time. The call to
 171  *         __tls_get_addr() will return the starting offset of the dynamic
 172  *         TLS block.
 173  *
 174  *      @dtpoff(x): calculate the tlsoffset relative to the TLS block.
 175  *
 176  *      @tpoff(x): calculate the tlsoffset relative to the TLS block.
 177  *
 178  *      @dtpmod(x): calculate the module id of the object containing symbol x.
 179  *
 180  * The calculations in the CALCULATION column are assumed to have
 181  * been performed before calling this function except for the addition of
 182  * the addresses in the instructions.
 183  */
 184 #if defined(_KERNEL)
 185 #define lml     0               /* Needed by arglist of REL_ERR_* macros */
 186 int
 187 do_reloc_krtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
 188     const char *file)
 189 #elif 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 }