Print this page
10908 Simplify SMAP relocations with krtld
@@ -21,13 +21,14 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Joyent, Inc.
+ */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* x86 relocation code.
*/
#include <sys/types.h>
@@ -117,12 +118,62 @@
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
-/* 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() */
@@ -219,10 +270,15 @@
*/
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) {