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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/intel/amd64/krtld/kobj_reloc.c
          +++ new/usr/src/uts/intel/amd64/krtld/kobj_reloc.c
↓ open down ↓ 111 lines elided ↑ open up ↑
 112  112          sdp->sdpd_offset = (uintptr_t)instr;
 113  113          sdp->sdpd_next = mp->sdt_probes;
 114  114          mp->sdt_probes = sdp;
 115  115  
 116  116          for (i = 0; i < SDT_NOPS; i++)
 117  117                  instr[i - 1] = SDT_NOP;
 118  118  
 119  119          return (0);
 120  120  }
 121  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 +
 122  173  int
 123  174  do_relocate(struct module *mp, char *reltbl, int nreloc, int relocsize,
 124  175      Addr baseaddr)
 125  176  {
 126  177          unsigned long stndx;
 127  178          unsigned long off;      /* can't be register for tnf_reloc_resolve() */
 128  179          register unsigned long reladdr, rend;
 129  180          register unsigned int rtype;
 130  181          unsigned long value;
 131  182          Elf64_Sxword addend;
↓ open down ↓ 81 lines elided ↑ open up ↑
 213  264                                  /*
 214  265                                   * It's global. Allow weak references.  If
 215  266                                   * the symbol is undefined, give TNF (the
 216  267                                   * kernel probes facility) a chance to see
 217  268                                   * if it's a probe site, and fix it up if so.
 218  269                                   */
 219  270                                  if (symref->st_shndx == SHN_UNDEF &&
 220  271                                      sdt_reloc_resolve(mp, mp->strings +
 221  272                                      symref->st_name, (uint8_t *)off) == 0)
 222  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;
 223  279  
 224  280                                  if (symref->st_shndx == SHN_UNDEF &&
 225  281                                      tnf_reloc_resolve(mp->strings +
 226  282                                      symref->st_name, &symref->st_value,
 227  283                                      &addend, off, &probelist, &taglist) != 0) {
 228  284                                          if (ELF_ST_BIND(symref->st_info)
 229  285                                              != STB_WEAK) {
 230  286                                                  _kobj_printf(ops,
 231  287                                                      "not found: %s\n",
 232  288                                                      mp->strings +
↓ open down ↓ 112 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX