Print this page
9059 Simplify SMAP relocations with krtld
Portions contributed by: John Levon <john.levon@joyent.com>
*** 117,126 ****
--- 117,177 ----
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, int nreloc, int relocsize,
Addr baseaddr)
{
unsigned long stndx;
*** 218,227 ****
--- 269,283 ----
*/
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) {