Print this page
10908 Simplify SMAP relocations with krtld


   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 2007 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 /*
  30  * x86 relocation code.
  31  */
  32 
  33 #include <sys/types.h>
  34 #include <sys/param.h>
  35 #include <sys/sysmacros.h>
  36 #include <sys/systm.h>
  37 #include <sys/user.h>
  38 #include <sys/bootconf.h>
  39 #include <sys/modctl.h>
  40 #include <sys/elf.h>
  41 #include <sys/kobj.h>
  42 #include <sys/kobj_impl.h>
  43 #include <sys/tnf.h>
  44 #include <sys/tnf_probe.h>
  45 
  46 #include "reloc.h"
  47 
  48 


 102          */
 103         if (strncmp(symname, sdt_prefix, strlen(sdt_prefix)) != 0)
 104                 return (1);
 105 
 106         symname += strlen(sdt_prefix);
 107 
 108         sdp = kobj_alloc(sizeof (sdt_probedesc_t), KM_WAIT);
 109         sdp->sdpd_name = kobj_alloc(strlen(symname) + 1, KM_WAIT);
 110         bcopy(symname, sdp->sdpd_name, strlen(symname) + 1);
 111 
 112         sdp->sdpd_offset = (uintptr_t)instr;
 113         sdp->sdpd_next = mp->sdt_probes;
 114         mp->sdt_probes = sdp;
 115 
 116         for (i = 0; i < SDT_NOPS; i++)
 117                 instr[i - 1] = SDT_NOP;
 118 
 119         return (0);
 120 }
 121 



















































 122 int
 123 /* ARGSUSED2 */
 124 do_relocate(struct module *mp, char *reltbl, Word relshtype, int nreloc,
 125         int relocsize, Addr baseaddr)
 126 {
 127         unsigned long stndx;
 128         unsigned long off;      /* can't be register for tnf_reloc_resolve() */
 129         register unsigned long reladdr, rend;
 130         register unsigned int rtype;
 131         unsigned long value;
 132         Elf64_Sxword addend;
 133         Sym *symref;
 134         int err = 0;
 135         tnf_probe_control_t *probelist = NULL;
 136         tnf_tag_data_t *taglist = NULL;
 137         int symnum;
 138         reladdr = (unsigned long)reltbl;
 139         rend = reladdr + nreloc * relocsize;
 140 
 141 #ifdef  KOBJ_DEBUG
 142         if (kobj_debug & D_RELOCATIONS) {
 143                 _kobj_printf(ops, "krtld:\ttype\t\t\toffset\t   addend"


 204                          * get symbol table entry - if symbol is local
 205                          * value is base address of this object
 206                          */
 207                         symref = (Sym *)
 208                             (mp->symtbl+(stndx * mp->symhdr->sh_entsize));
 209 
 210                         if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) {
 211                                 /* *** this is different for .o and .so */
 212                                 value = symref->st_value;
 213                         } else {
 214                                 /*
 215                                  * It's global. Allow weak references.  If
 216                                  * the symbol is undefined, give TNF (the
 217                                  * kernel probes facility) a chance to see
 218                                  * if it's a probe site, and fix it up if so.
 219                                  */
 220                                 if (symref->st_shndx == SHN_UNDEF &&
 221                                     sdt_reloc_resolve(mp, mp->strings +
 222                                     symref->st_name, (uint8_t *)off) == 0)
 223                                         continue;





 224 
 225                                 if (symref->st_shndx == SHN_UNDEF &&
 226                                     tnf_reloc_resolve(mp->strings +
 227                                     symref->st_name, &symref->st_value,
 228                                     &addend, off, &probelist, &taglist) != 0) {
 229                                         if (ELF_ST_BIND(symref->st_info)
 230                                             != STB_WEAK) {
 231                                                 _kobj_printf(ops,
 232                                                     "not found: %s\n",
 233                                                     mp->strings +
 234                                                     symref->st_name);
 235                                                 err = 1;
 236                                         }
 237                                         continue;
 238                                 } else { /* symbol found  - relocate */
 239                                         /*
 240                                          * calculate location of definition
 241                                          * - symbol value plus base address of
 242                                          * containing shared object
 243                                          */




   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 2007 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 /*
  27  * Copyright 2019 Joyent, Inc.
  28  */
  29 


  30 /*
  31  * x86 relocation code.
  32  */
  33 
  34 #include <sys/types.h>
  35 #include <sys/param.h>
  36 #include <sys/sysmacros.h>
  37 #include <sys/systm.h>
  38 #include <sys/user.h>
  39 #include <sys/bootconf.h>
  40 #include <sys/modctl.h>
  41 #include <sys/elf.h>
  42 #include <sys/kobj.h>
  43 #include <sys/kobj_impl.h>
  44 #include <sys/tnf.h>
  45 #include <sys/tnf_probe.h>
  46 
  47 #include "reloc.h"
  48 
  49 


 103          */
 104         if (strncmp(symname, sdt_prefix, strlen(sdt_prefix)) != 0)
 105                 return (1);
 106 
 107         symname += strlen(sdt_prefix);
 108 
 109         sdp = kobj_alloc(sizeof (sdt_probedesc_t), KM_WAIT);
 110         sdp->sdpd_name = kobj_alloc(strlen(symname) + 1, KM_WAIT);
 111         bcopy(symname, sdp->sdpd_name, strlen(symname) + 1);
 112 
 113         sdp->sdpd_offset = (uintptr_t)instr;
 114         sdp->sdpd_next = mp->sdt_probes;
 115         mp->sdt_probes = sdp;
 116 
 117         for (i = 0; i < SDT_NOPS; i++)
 118                 instr[i - 1] = SDT_NOP;
 119 
 120         return (0);
 121 }
 122 
 123 
 124 /*
 125  * We're relying on the fact that the call we're replacing is
 126  * call (e8) plus 4 bytes of address, making a 5 byte instruction
 127  */
 128 #define NOP_INSTR       0x90
 129 #define SMAP_NOPS       5
 130 
 131 /*
 132  * Currently the only call replaced as a hot inline
 133  * is smap_enable() and smap_disable(). If more are needed
 134  * we should probably come up with an sdt probe like prefix
 135  * and look for those instead of exact call names.
 136  */
 137 static int
 138 smap_reloc_resolve(struct module *mp, char *symname, uint8_t *instr)
 139 {
 140         uint_t symlen;
 141         hotinline_desc_t *hid;
 142 
 143         if (strcmp(symname, "smap_enable") == 0 ||
 144             strcmp(symname, "smap_disable") == 0) {
 145 
 146 #ifdef  KOBJ_DEBUG
 147                 if (kobj_debug & D_RELOCATIONS) {
 148                         _kobj_printf(ops, "smap_reloc_resolve: %s relocating "
 149                             "enable/disable_smap\n", mp->filename);
 150                 }
 151 #endif
 152 
 153                 hid = kobj_alloc(sizeof (hotinline_desc_t), KM_WAIT);
 154                 symlen = strlen(symname) + 1;
 155                 hid->hid_symname = kobj_alloc(symlen, KM_WAIT);
 156                 bcopy(symname, hid->hid_symname, symlen);
 157 
 158                 /*
 159                  * We backtrack one byte here to consume the call
 160                  * instruction itself.
 161                  */
 162                 hid->hid_instr_offset = (uintptr_t)instr - 1;
 163                 hid->hid_next = mp->hi_calls;
 164                 mp->hi_calls = hid;
 165 
 166                 memset((void *)hid->hid_instr_offset, NOP_INSTR, SMAP_NOPS);
 167 
 168                 return (0);
 169         }
 170 
 171         return (1);
 172 }
 173 
 174 int

 175 do_relocate(struct module *mp, char *reltbl, Word relshtype, int nreloc,
 176     int relocsize, Addr baseaddr)
 177 {
 178         unsigned long stndx;
 179         unsigned long off;      /* can't be register for tnf_reloc_resolve() */
 180         register unsigned long reladdr, rend;
 181         register unsigned int rtype;
 182         unsigned long value;
 183         Elf64_Sxword addend;
 184         Sym *symref;
 185         int err = 0;
 186         tnf_probe_control_t *probelist = NULL;
 187         tnf_tag_data_t *taglist = NULL;
 188         int symnum;
 189         reladdr = (unsigned long)reltbl;
 190         rend = reladdr + nreloc * relocsize;
 191 
 192 #ifdef  KOBJ_DEBUG
 193         if (kobj_debug & D_RELOCATIONS) {
 194                 _kobj_printf(ops, "krtld:\ttype\t\t\toffset\t   addend"


 255                          * get symbol table entry - if symbol is local
 256                          * value is base address of this object
 257                          */
 258                         symref = (Sym *)
 259                             (mp->symtbl+(stndx * mp->symhdr->sh_entsize));
 260 
 261                         if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) {
 262                                 /* *** this is different for .o and .so */
 263                                 value = symref->st_value;
 264                         } else {
 265                                 /*
 266                                  * It's global. Allow weak references.  If
 267                                  * the symbol is undefined, give TNF (the
 268                                  * kernel probes facility) a chance to see
 269                                  * if it's a probe site, and fix it up if so.
 270                                  */
 271                                 if (symref->st_shndx == SHN_UNDEF &&
 272                                     sdt_reloc_resolve(mp, mp->strings +
 273                                     symref->st_name, (uint8_t *)off) == 0)
 274                                         continue;
 275 
 276                                 if (symref->st_shndx == SHN_UNDEF &&
 277                                     smap_reloc_resolve(mp, mp->strings +
 278                                     symref->st_name, (uint8_t *)off) == 0)
 279                                         continue;
 280 
 281                                 if (symref->st_shndx == SHN_UNDEF &&
 282                                     tnf_reloc_resolve(mp->strings +
 283                                     symref->st_name, &symref->st_value,
 284                                     &addend, off, &probelist, &taglist) != 0) {
 285                                         if (ELF_ST_BIND(symref->st_info)
 286                                             != STB_WEAK) {
 287                                                 _kobj_printf(ops,
 288                                                     "not found: %s\n",
 289                                                     mp->strings +
 290                                                     symref->st_name);
 291                                                 err = 1;
 292                                         }
 293                                         continue;
 294                                 } else { /* symbol found  - relocate */
 295                                         /*
 296                                          * calculate location of definition
 297                                          * - symbol value plus base address of
 298                                          * containing shared object
 299                                          */