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 */
|