Print this page
9059 Simplify SMAP relocations with krtld
Portions contributed by: John Levon <john.levon@joyent.com>


 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 do_relocate(struct module *mp, char *reltbl, int nreloc, int relocsize,
 124     Addr baseaddr)
 125 {
 126         unsigned long stndx;
 127         unsigned long off;      /* can't be register for tnf_reloc_resolve() */
 128         register unsigned long reladdr, rend;
 129         register unsigned int rtype;
 130         unsigned long value;
 131         Elf64_Sxword addend;
 132         Sym *symref = NULL;
 133         int err = 0;
 134         tnf_probe_control_t *probelist = NULL;
 135         tnf_tag_data_t *taglist = NULL;
 136         int symnum;
 137         reladdr = (unsigned long)reltbl;
 138         rend = reladdr + nreloc * relocsize;
 139 
 140 #ifdef  KOBJ_DEBUG
 141         if (kobj_debug & D_RELOCATIONS) {


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





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




 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 
 123 /*
 124  * We're relying on the fact that the call we're replacing is
 125  * call (e8) plus 4 bytes of address, making a 5 byte instruction
 126  */
 127 #define NOP_INSTR       0x90
 128 #define SMAP_NOPS       5
 129 
 130 /*
 131  * Currently the only call replaced as a hot inline
 132  * is smap_enable() and smap_disable(). If more are needed
 133  * we should probably come up with an sdt probe like prefix
 134  * and look for those instead of exact call names.
 135  */
 136 static int
 137 smap_reloc_resolve(struct module *mp, char *symname, uint8_t *instr)
 138 {
 139         uint_t symlen;
 140         hotinline_desc_t *hid;
 141 
 142         if (strcmp(symname, "smap_enable") == 0 ||
 143             strcmp(symname, "smap_disable") == 0) {
 144 
 145 #ifdef  KOBJ_DEBUG
 146                 if (kobj_debug & D_RELOCATIONS) {
 147                         _kobj_printf(ops, "smap_reloc_resolve: %s relocating "
 148                             "enable/disable_smap\n", mp->filename);
 149                 }
 150 #endif
 151 
 152                 hid = kobj_alloc(sizeof (hotinline_desc_t), KM_WAIT);
 153                 symlen = strlen(symname) + 1;
 154                 hid->hid_symname = kobj_alloc(symlen, KM_WAIT);
 155                 bcopy(symname, hid->hid_symname, symlen);
 156 
 157                 /*
 158                  * We backtrack one byte here to consume the call
 159                  * instruction itself.
 160                  */
 161                 hid->hid_instr_offset = (uintptr_t)instr - 1;
 162                 hid->hid_next = mp->hi_calls;
 163                 mp->hi_calls = hid;
 164 
 165                 memset((void *)hid->hid_instr_offset, NOP_INSTR, SMAP_NOPS);
 166 
 167                 return (0);
 168         }
 169 
 170         return (1);
 171 }
 172 
 173 int
 174 do_relocate(struct module *mp, char *reltbl, int nreloc, int relocsize,
 175     Addr baseaddr)
 176 {
 177         unsigned long stndx;
 178         unsigned long off;      /* can't be register for tnf_reloc_resolve() */
 179         register unsigned long reladdr, rend;
 180         register unsigned int rtype;
 181         unsigned long value;
 182         Elf64_Sxword addend;
 183         Sym *symref = NULL;
 184         int err = 0;
 185         tnf_probe_control_t *probelist = NULL;
 186         tnf_tag_data_t *taglist = NULL;
 187         int symnum;
 188         reladdr = (unsigned long)reltbl;
 189         rend = reladdr + nreloc * relocsize;
 190 
 191 #ifdef  KOBJ_DEBUG
 192         if (kobj_debug & D_RELOCATIONS) {


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