xref: /illumos-gate/usr/src/lib/libproc/amd64/Pisadep.c (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/stack.h>
30 #include <sys/regset.h>
31 #include <sys/frame.h>
32 #include <sys/sysmacros.h>
33 #include <sys/trap.h>
34 
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <sys/types.h>
38 #include <errno.h>
39 #include <string.h>
40 
41 #include "Pcontrol.h"
42 #include "Pstack.h"
43 
44 #define	M_PLT_NRSV		1	/* reserved PLT entries */
45 #define	M_PLT_ENTSIZE		16	/* size of each PLT entry */
46 
47 static uchar_t int_syscall_instr[] = { 0xCD, T_SYSCALLINT };
48 static uchar_t syscall_instr[] = { 0x0f, 0x05 };
49 
50 const char *
51 Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr)
52 {
53 	map_info_t *mp = Paddr2mptr(P, pltaddr);
54 	file_info_t *fp;
55 	size_t i;
56 	uintptr_t r_addr;
57 
58 	if (mp == NULL || (fp = mp->map_file) == NULL ||
59 	    fp->file_plt_base == 0 ||
60 	    pltaddr - fp->file_plt_base >= fp->file_plt_size) {
61 		errno = EINVAL;
62 		return (NULL);
63 	}
64 
65 	i = (pltaddr - fp->file_plt_base) / M_PLT_ENTSIZE - M_PLT_NRSV;
66 
67 	if (P->status.pr_dmodel == PR_MODEL_LP64) {
68 		Elf64_Rela r;
69 
70 		r_addr = fp->file_jmp_rel + i * sizeof (r);
71 
72 		if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
73 		    (i = ELF64_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
74 			Elf_Data *data = fp->file_dynsym.sym_data;
75 			Elf64_Sym *symp = &(((Elf64_Sym *)data->d_buf)[i]);
76 
77 			return (fp->file_dynsym.sym_strs + symp->st_name);
78 		}
79 	} else {
80 		Elf32_Rel r;
81 
82 		r_addr = fp->file_jmp_rel + i * sizeof (r);
83 
84 		if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
85 		    (i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
86 			Elf_Data *data = fp->file_dynsym.sym_data;
87 			Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]);
88 
89 			return (fp->file_dynsym.sym_strs + symp->st_name);
90 		}
91 	}
92 
93 	return (NULL);
94 }
95 
96 int
97 Pissyscall(struct ps_prochandle *P, uintptr_t addr)
98 {
99 	uchar_t instr[16];
100 
101 	if (P->status.pr_dmodel == PR_MODEL_LP64) {
102 		if (Pread(P, instr, sizeof (syscall_instr), addr) !=
103 		    sizeof (syscall_instr) ||
104 		    memcmp(instr, syscall_instr, sizeof (syscall_instr)) != 0)
105 			return (0);
106 		else
107 			return (1);
108 	}
109 
110 	if (Pread(P, instr, sizeof (int_syscall_instr), addr) !=
111 	    sizeof (int_syscall_instr))
112 		return (0);
113 
114 	if (memcmp(instr, int_syscall_instr, sizeof (int_syscall_instr)) == 0)
115 		return (1);
116 
117 	return (0);
118 }
119 
120 int
121 Pissyscall_prev(struct ps_prochandle *P, uintptr_t addr, uintptr_t *dst)
122 {
123 	int ret;
124 
125 	if (P->status.pr_dmodel == PR_MODEL_LP64) {
126 		if (Pissyscall(P, addr - sizeof (syscall_instr))) {
127 			if (dst)
128 				*dst = addr - sizeof (syscall_instr);
129 			return (1);
130 		}
131 		return (0);
132 	}
133 
134 	if ((ret = Pissyscall(P, addr - sizeof (int_syscall_instr))) != 0) {
135 		if (dst)
136 			*dst = addr - sizeof (int_syscall_instr);
137 		return (ret);
138 	}
139 
140 	return (0);
141 }
142 
143 int
144 Pissyscall_text(struct ps_prochandle *P, const void *buf, size_t buflen)
145 {
146 	if (P->status.pr_dmodel == PR_MODEL_LP64) {
147 		if (buflen >= sizeof (syscall_instr) &&
148 		    memcmp(buf, syscall_instr, sizeof (syscall_instr)) == 0)
149 			return (1);
150 		else
151 			return (0);
152 	}
153 
154 	if (buflen < sizeof (int_syscall_instr))
155 		return (0);
156 
157 	if (memcmp(buf, int_syscall_instr, sizeof (int_syscall_instr)) == 0)
158 		return (1);
159 
160 	return (0);
161 }
162 
163 #define	TR_ARG_MAX 6	/* Max args to print, same as SPARC */
164 
165 /*
166  * Given a return address, determine the likely number of arguments
167  * that were pushed on the stack prior to its execution.  We do this by
168  * expecting that a typical call sequence consists of pushing arguments on
169  * the stack, executing a call instruction, and then performing an add
170  * on %esp to restore it to the value prior to pushing the arguments for
171  * the call.  We attempt to detect such an add, and divide the addend
172  * by the size of a word to determine the number of pushed arguments.
173  *
174  * If we do not find such an add, this does not necessarily imply that the
175  * function took no arguments. It is not possible to reliably detect such a
176  * void function because hand-coded assembler does not always perform an add
177  * to %esp immediately after the "call" instruction (eg. _sys_call()).
178  * Because of this, we default to returning MIN(sz, TR_ARG_MAX) instead of 0
179  * in the absence of an add to %esp.
180  */
181 static ulong_t
182 argcount(struct ps_prochandle *P, uint32_t pc, ssize_t sz)
183 {
184 	uchar_t instr[6];
185 	ulong_t count, max;
186 
187 	max = MIN(sz / sizeof (uint32_t), TR_ARG_MAX);
188 
189 	/*
190 	 * Read the instruction at the return location.
191 	 */
192 	if (Pread(P, instr, sizeof (instr), (uintptr_t)pc) != sizeof (instr))
193 		return (max);
194 
195 	if (instr[1] != 0xc4)
196 		return (max);
197 
198 	switch (instr[0]) {
199 	case 0x81:	/* count is a longword */
200 		count = instr[2]+(instr[3]<<8)+(instr[4]<<16)+(instr[5]<<24);
201 		break;
202 	case 0x83:	/* count is a byte */
203 		count = instr[2];
204 		break;
205 	default:
206 		return (max);
207 	}
208 
209 	count /= sizeof (uint32_t);
210 	return (MIN(count, max));
211 }
212 
213 static void
214 ucontext_32_to_prgregs(const ucontext32_t *uc, prgregset_t dst)
215 {
216 	const greg32_t *src = &uc->uc_mcontext.gregs[0];
217 
218 	dst[REG_DS] = (uint16_t)src[DS];
219 	dst[REG_ES] = (uint16_t)src[ES];
220 
221 	dst[REG_GS] = (uint16_t)src[GS];
222 	dst[REG_FS] = (uint16_t)src[FS];
223 	dst[REG_SS] = (uint16_t)src[SS];
224 	dst[REG_RSP] = (uint32_t)src[UESP];
225 	dst[REG_RFL] = src[EFL];
226 	dst[REG_CS] = (uint16_t)src[CS];
227 	dst[REG_RIP] = (uint32_t)src[EIP];
228 	dst[REG_ERR] = (uint32_t)src[ERR];
229 	dst[REG_TRAPNO] = (uint32_t)src[TRAPNO];
230 	dst[REG_RAX] = (uint32_t)src[EAX];
231 	dst[REG_RCX] = (uint32_t)src[ECX];
232 	dst[REG_RDX] = (uint32_t)src[EDX];
233 	dst[REG_RBX] = (uint32_t)src[EBX];
234 	dst[REG_RBP] = (uint32_t)src[EBP];
235 	dst[REG_RSI] = (uint32_t)src[ESI];
236 	dst[REG_RDI] = (uint32_t)src[EDI];
237 }
238 
239 static int
240 Pstack_iter32(struct ps_prochandle *P, const prgregset_t regs,
241     proc_stack_f *func, void *arg)
242 {
243 	prgreg_t *prevfp = NULL;
244 	uint_t pfpsize = 0;
245 	int nfp = 0;
246 	struct {
247 		prgreg32_t fp;
248 		prgreg32_t pc;
249 		prgreg32_t args[32];
250 	} frame;
251 	uint_t argc;
252 	ssize_t sz;
253 	prgregset_t gregs;
254 	uint32_t fp, pfp, pc;
255 	long args[32];
256 	int rv;
257 	int i;
258 
259 	/*
260 	 * Type definition for a structure corresponding to an IA32
261 	 * signal frame.  Refer to the comments in Pstack.c for more info
262 	 */
263 	typedef struct {
264 		prgreg32_t fp;
265 		prgreg32_t pc;
266 		int signo;
267 		caddr32_t ucp;
268 		caddr32_t sip;
269 	} sf_t;
270 
271 	uclist_t ucl;
272 	ucontext32_t uc;
273 	uintptr_t uc_addr;
274 
275 	init_uclist(&ucl, P);
276 	(void) memcpy(gregs, regs, sizeof (gregs));
277 
278 	fp = regs[R_FP];
279 	pc = regs[R_PC];
280 
281 	while (fp != 0 || pc != 0) {
282 		if (stack_loop(fp, &prevfp, &nfp, &pfpsize))
283 			break;
284 
285 		if (fp != 0 &&
286 		    (sz = Pread(P, &frame, sizeof (frame), (uintptr_t)fp)
287 		    >= (ssize_t)(2* sizeof (uint32_t)))) {
288 			/*
289 			 * One more trick for signal frames: the kernel sets
290 			 * the return pc of the signal frame to 0xffffffff on
291 			 * Intel IA32, so argcount won't work.
292 			 */
293 			if (frame.pc != -1L) {
294 				sz -= 2* sizeof (uint32_t);
295 				argc = argcount(P, (uint32_t)frame.pc, sz);
296 			} else
297 				argc = 3; /* sighandler(signo, sip, ucp) */
298 		} else {
299 			(void) memset(&frame, 0, sizeof (frame));
300 			argc = 0;
301 		}
302 
303 		gregs[R_FP] = fp;
304 		gregs[R_PC] = pc;
305 
306 		for (i = 0; i < argc; i++)
307 			args[i] = (uint32_t)frame.args[i];
308 
309 		if ((rv = func(arg, gregs, argc, args)) != 0)
310 			break;
311 
312 		/*
313 		 * In order to allow iteration over java frames (which can have
314 		 * their own frame pointers), we allow the iterator to change
315 		 * the contents of gregs.  If we detect a change, then we assume
316 		 * that the new values point to the next frame.
317 		 */
318 		if (gregs[R_FP] != fp || gregs[R_PC] != pc) {
319 			fp = gregs[R_FP];
320 			pc = gregs[R_PC];
321 			continue;
322 		}
323 
324 		pfp = fp;
325 		fp = frame.fp;
326 		pc = frame.pc;
327 
328 		if (find_uclink(&ucl, pfp + sizeof (sf_t)))
329 			uc_addr = pfp + sizeof (sf_t);
330 		else
331 			uc_addr = NULL;
332 
333 		if (uc_addr != NULL &&
334 		    Pread(P, &uc, sizeof (uc), uc_addr) == sizeof (uc)) {
335 			ucontext_32_to_prgregs(&uc, gregs);
336 			fp = gregs[R_FP];
337 			pc = gregs[R_PC];
338 		}
339 	}
340 
341 	if (prevfp)
342 		free(prevfp);
343 
344 	free_uclist(&ucl);
345 	return (rv);
346 }
347 
348 static void
349 ucontext_n_to_prgregs(const ucontext_t *src, prgregset_t dst)
350 {
351 	(void) memcpy(dst, src->uc_mcontext.gregs, sizeof (gregset_t));
352 }
353 
354 
355 int
356 Pstack_iter(struct ps_prochandle *P, const prgregset_t regs,
357 	proc_stack_f *func, void *arg)
358 {
359 	struct {
360 		uintptr_t fp;
361 		uintptr_t pc;
362 	} frame;
363 
364 	uint_t pfpsize = 0;
365 	prgreg_t *prevfp = NULL;
366 	prgreg_t fp, pfp;
367 	prgreg_t pc;
368 
369 	prgregset_t gregs;
370 	int nfp = 0;
371 
372 	uclist_t ucl;
373 	int rv = 0;
374 	int argc;
375 
376 	uintptr_t uc_addr;
377 	ucontext_t uc;
378 
379 	/*
380 	 * Type definition for a structure corresponding to an IA32
381 	 * signal frame.  Refer to the comments in Pstack.c for more info
382 	 */
383 	typedef struct {
384 		prgreg_t fp;
385 		prgreg_t pc;
386 		prgreg_t signo;
387 		siginfo_t *sip;
388 	} sigframe_t;
389 	prgreg_t args[32];
390 
391 	if (P->status.pr_dmodel != PR_MODEL_LP64)
392 		return (Pstack_iter32(P, regs, func, arg));
393 
394 	init_uclist(&ucl, P);
395 	(void) memcpy(gregs, regs, sizeof (gregs));
396 
397 	fp = gregs[R_FP];
398 	pc = gregs[R_PC];
399 
400 	while (fp != 0 || pc != 0) {
401 
402 		if (stack_loop(fp, &prevfp, &nfp, &pfpsize))
403 			break;
404 
405 		if (fp != 0 &&
406 		    Pread(P, &frame, sizeof (frame), (uintptr_t)fp) ==
407 		    sizeof (frame)) {
408 
409 			if (frame.pc != -1) {
410 				/*
411 				 * Function arguments are not available on
412 				 * amd64 without extensive DWARF processing.
413 				 */
414 				argc = 0;
415 			} else {
416 				argc = 3;
417 				args[2] = fp + sizeof (sigframe_t);
418 				if (Pread(P, &args, 2 * sizeof (prgreg_t),
419 				    fp + 2 * sizeof (prgreg_t)) !=
420 				    2 * sizeof (prgreg_t))
421 					argc = 0;
422 			}
423 		} else {
424 			(void) memset(&frame, 0, sizeof (frame));
425 			argc = 0;
426 		}
427 
428 		gregs[R_FP] = fp;
429 		gregs[R_PC] = pc;
430 
431 		if ((rv = func(arg, gregs, argc, args)) != 0)
432 			break;
433 
434 		pfp = fp;
435 		fp = frame.fp;
436 		pc = frame.pc;
437 
438 		if (pc == -1 && find_uclink(&ucl, pfp + sizeof (sigframe_t))) {
439 			uc_addr = pfp + sizeof (sigframe_t);
440 
441 			if (Pread(P, &uc, sizeof (uc), uc_addr)
442 			    == sizeof (uc)) {
443 				ucontext_n_to_prgregs(&uc, gregs);
444 				fp = gregs[R_FP];
445 				pc = gregs[R_PC];
446 			}
447 		}
448 	}
449 
450 	if (prevfp)
451 		free(prevfp);
452 
453 	free_uclist(&ucl);
454 
455 	return (rv);
456 }
457 
458 uintptr_t
459 Psyscall_setup(struct ps_prochandle *P, int nargs, int sysindex, uintptr_t sp)
460 {
461 	if (P->status.pr_dmodel == PR_MODEL_ILP32) {
462 		sp -= sizeof (int) * (nargs+2);
463 
464 		P->status.pr_lwp.pr_reg[REG_RAX] = sysindex;
465 		P->status.pr_lwp.pr_reg[REG_RSP] = sp;
466 		P->status.pr_lwp.pr_reg[REG_RIP] = P->sysaddr;
467 	} else {
468 		int pusharg = (nargs > 6) ? nargs - 6: 0;
469 
470 		sp -= sizeof (int64_t) * (pusharg+2);
471 
472 		P->status.pr_lwp.pr_reg[REG_RAX] = sysindex;
473 		P->status.pr_lwp.pr_reg[REG_RSP] = sp;
474 		P->status.pr_lwp.pr_reg[REG_RIP] = P->sysaddr;
475 	}
476 
477 	return (sp);
478 }
479 
480 int
481 Psyscall_copyinargs(struct ps_prochandle *P, int nargs, argdes_t *argp,
482     uintptr_t ap)
483 {
484 	if (P->status.pr_dmodel == PR_MODEL_ILP32) {
485 		int32_t arglist[MAXARGS+2];
486 		int i;
487 		argdes_t *adp;
488 
489 		for (i = 0, adp = argp; i < nargs; i++, adp++)
490 			arglist[1 + i] = (int32_t)adp->arg_value;
491 
492 		arglist[0] = P->status.pr_lwp.pr_reg[REG_RIP];
493 		if (Pwrite(P, &arglist[0], sizeof (int) * (nargs+1),
494 		    (uintptr_t)ap) != sizeof (int) * (nargs+1))
495 			return (-1);
496 	} else {
497 		int64_t arglist[MAXARGS+2];
498 		int i;
499 		argdes_t *adp;
500 		int pusharg = (nargs > 6) ? nargs - 6: 0;
501 
502 		for (i = 0, adp = argp; i < nargs; i++, adp++) {
503 			switch (i) {
504 			case 0:
505 				(void) Pputareg(P, REG_RDI, adp->arg_value);
506 				break;
507 			case 1:
508 				(void) Pputareg(P, REG_RSI, adp->arg_value);
509 				break;
510 			case 2:
511 				(void) Pputareg(P, REG_RDX, adp->arg_value);
512 				break;
513 			case 3:
514 				(void) Pputareg(P, REG_RCX, adp->arg_value);
515 				break;
516 			case 4:
517 				(void) Pputareg(P, REG_R8, adp->arg_value);
518 				break;
519 			case 5:
520 				(void) Pputareg(P, REG_R9, adp->arg_value);
521 				break;
522 			default:
523 				arglist[i - 5] = (uint64_t)adp->arg_value;
524 				break;
525 			}
526 		}
527 
528 		arglist[0] = P->status.pr_lwp.pr_reg[REG_RIP];
529 
530 		if (Pwrite(P, &arglist[0],
531 		    sizeof (int64_t) * (pusharg + 1), ap) !=
532 		    sizeof (int64_t) * (pusharg + 1))
533 			return (-1);
534 	}
535 
536 	return (0);
537 }
538 
539 int
540 Psyscall_copyoutargs(struct ps_prochandle *P, int nargs, argdes_t *argp,
541     uintptr_t ap)
542 {
543 	if (P->status.pr_dmodel == PR_MODEL_ILP32) {
544 		uint32_t arglist[MAXARGS + 2];
545 		int i;
546 		argdes_t *adp;
547 
548 		if (Pread(P, &arglist[0], sizeof (int) * (nargs+1),
549 		    (uintptr_t)ap) != sizeof (int) * (nargs+1))
550 			return (-1);
551 
552 		for (i = 0, adp = argp; i < nargs; i++, adp++)
553 			adp->arg_value = arglist[i];
554 	} else {
555 		int pusharg = (nargs > 6) ? nargs - 6: 0;
556 		int64_t arglist[MAXARGS+2];
557 		int i;
558 		argdes_t *adp;
559 
560 		if (pusharg  > 0 &&
561 		    Pread(P, &arglist[0], sizeof (int64_t) * (pusharg + 1),
562 		    ap) != sizeof (int64_t) * (pusharg + 1))
563 			return (-1);
564 
565 		for (i = 0, adp = argp; i < nargs; i++, adp++) {
566 			switch (i) {
567 			case 0:
568 				adp->arg_value =
569 				    P->status.pr_lwp.pr_reg[REG_RDI];
570 				break;
571 			case 1:
572 				adp->arg_value =
573 				    P->status.pr_lwp.pr_reg[REG_RSI];
574 				break;
575 			case 2:
576 				adp->arg_value =
577 				    P->status.pr_lwp.pr_reg[REG_RDX];
578 				break;
579 			case 3:
580 				adp->arg_value =
581 				    P->status.pr_lwp.pr_reg[REG_RCX];
582 				break;
583 			case 4:
584 				adp->arg_value =
585 				    P->status.pr_lwp.pr_reg[REG_R8];
586 				break;
587 			case 5:
588 				adp->arg_value =
589 				    P->status.pr_lwp.pr_reg[REG_R9];
590 				break;
591 			default:
592 				adp->arg_value = arglist[i - 6];
593 				break;
594 			}
595 		}
596 
597 		return (0);
598 	}
599 
600 	return (0);
601 }
602