Print this page
10908 Simplify SMAP relocations with krtld

*** 21,33 **** /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - #pragma ident "%Z%%M% %I% %E% SMI" - /* * x86 relocation code. */ #include <sys/types.h> --- 21,34 ---- /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ + /* + * Copyright 2019 Joyent, Inc. + */ /* * x86 relocation code. */ #include <sys/types.h>
*** 117,128 **** instr[i - 1] = SDT_NOP; return (0); } int - /* ARGSUSED2 */ do_relocate(struct module *mp, char *reltbl, Word relshtype, int nreloc, int relocsize, Addr baseaddr) { unsigned long stndx; unsigned long off; /* can't be register for tnf_reloc_resolve() */ --- 118,179 ---- instr[i - 1] = SDT_NOP; return (0); } + + /* + * We're relying on the fact that the call we're replacing is + * call (e8) plus 4 bytes of address, making a 5 byte instruction + */ + #define NOP_INSTR 0x90 + #define SMAP_NOPS 5 + + /* + * Currently the only call replaced as a hot inline + * is smap_enable() and smap_disable(). If more are needed + * we should probably come up with an sdt probe like prefix + * and look for those instead of exact call names. + */ + static int + smap_reloc_resolve(struct module *mp, char *symname, uint8_t *instr) + { + uint_t symlen; + hotinline_desc_t *hid; + + if (strcmp(symname, "smap_enable") == 0 || + strcmp(symname, "smap_disable") == 0) { + + #ifdef KOBJ_DEBUG + if (kobj_debug & D_RELOCATIONS) { + _kobj_printf(ops, "smap_reloc_resolve: %s relocating " + "enable/disable_smap\n", mp->filename); + } + #endif + + hid = kobj_alloc(sizeof (hotinline_desc_t), KM_WAIT); + symlen = strlen(symname) + 1; + hid->hid_symname = kobj_alloc(symlen, KM_WAIT); + bcopy(symname, hid->hid_symname, symlen); + + /* + * We backtrack one byte here to consume the call + * instruction itself. + */ + hid->hid_instr_offset = (uintptr_t)instr - 1; + hid->hid_next = mp->hi_calls; + mp->hi_calls = hid; + + memset((void *)hid->hid_instr_offset, NOP_INSTR, SMAP_NOPS); + + return (0); + } + + return (1); + } + int do_relocate(struct module *mp, char *reltbl, Word relshtype, int nreloc, int relocsize, Addr baseaddr) { unsigned long stndx; unsigned long off; /* can't be register for tnf_reloc_resolve() */
*** 219,228 **** --- 270,284 ---- */ if (symref->st_shndx == SHN_UNDEF && sdt_reloc_resolve(mp, mp->strings + symref->st_name, (uint8_t *)off) == 0) continue; + + if (symref->st_shndx == SHN_UNDEF && + smap_reloc_resolve(mp, mp->strings + + symref->st_name, (uint8_t *)off) == 0) + continue; if (symref->st_shndx == SHN_UNDEF && tnf_reloc_resolve(mp->strings + symref->st_name, &symref->st_value, &addend, off, &probelist, &taglist) != 0) {