示例#1
0
static void
stack_capture(struct stack *st, struct frame *frame)
{
	struct frame *fp;
	vm_offset_t callpc;

	stack_zero(st);
	fp = frame;
	for (;;) {
		if (!INKERNEL((vm_offset_t)fp) ||
		    !ALIGNED_POINTER(fp, uint64_t))
                        break;
		callpc = fp->fr_pc;
		if (!INKERNEL(callpc))
			break;
		/* Don't bother traversing trap frames. */
		if ((callpc > (uint64_t)tl_trap_begin &&
		    callpc < (uint64_t)tl_trap_end) ||
		    (callpc > (uint64_t)tl_text_begin &&
		    callpc < (uint64_t)tl_text_end))
			break;
		if (stack_put(st, callpc) == -1)
			break;
		if (v9next_frame(fp) <= fp ||
		    v9next_frame(fp) >= frame + KSTACK_PAGES * PAGE_SIZE)
			break;
		fp = v9next_frame(fp);
	}
}
示例#2
0
static void
kgdb_set_proc_cmd (char *arg, int from_tty)
{
	CORE_ADDR addr;
	struct kthr *thr;

	if (!arg)
		error_no_arg ("proc address for the new context");

	if (kvm == NULL)
		error ("only supported for core file target");

	addr = (CORE_ADDR) parse_and_eval_address (arg);

	if (!INKERNEL (addr)) {
		thr = kgdb_thr_lookup_pid((int)addr);
		if (thr == NULL)
			error ("invalid pid");
	} else {
		thr = kgdb_thr_lookup_paddr(addr);
		if (thr == NULL)
			error("invalid proc address");
	}
	kgdb_switch_to_thread(thr->tid);
}
示例#3
0
static struct ksample_stack *
stack_capture_kernel(struct thread *thread)
{
        struct ksample_stack *retval = NULL;
        register_t rbp;
        struct amd64_frame *frame;
        size_t depth = 0;
        static const size_t MAXDEPTH = 4096 / sizeof(vm_offset_t);
        caddr_t *pcs = NULL;

        pcs = malloc(sizeof(*pcs) * MAXDEPTH, M_TEMP, M_WAITOK | M_ZERO);

        if (pcs == NULL) {
                return NULL;
        }

        frame  = (struct amd64_frame*)thread->td_pcb->pcb_rbp;
        rbp = (register_t)frame;

        while (1) {
                vm_offset_t callpc;

                if (!INKERNEL((long)frame))
                        break;
                callpc = frame->f_retaddr;
                if (!INKERNEL(callpc))
                        break;
                if (depth > MAXDEPTH)
                        break;
                pcs[depth++] = (caddr_t)callpc;
                if (frame->f_frame <= frame ||
                    (vm_offset_t)frame->f_frame >=
                    (vm_offset_t)rbp + KSTACK_PAGES * PAGE_SIZE)
                        break;
                frame = frame->f_frame;
        }
//      printf("%s(%d):  depth = %u\n", __FUNCTION__, __LINE__, (unsigned int)depth);
        retval = malloc(sizeof(struct ksample_stack) + depth * sizeof(caddr_t), M_TEMP, M_WAITOK);
        if (retval) {
                retval->depth = depth;
                bcopy(pcs, retval->pcs, depth * sizeof(pcs[0]));
        }
//	printf("%s(%d)\n", __FUNCTION__, __LINE__);
        free(pcs, M_TEMP);
        return retval;
}
示例#4
0
setcor()
{

	fcor = datmap.ufd = getfile(corfil,2);
	if (kernel && fcor != -1 && INKERNEL(filhdr.a_entry)) {
		struct stat stb;

		kcore = 1;
		fstat(fcor, &stb);
		datmap.b1 = 0;
		datmap.e1 = -1;
		if (kernel == 0 && (stb.st_mode & S_IFREG))
			datmap.b1 = 0x80000000;
		lookup("_Sysmap");
		sbr = cursym->n_value;
		lookup("_Syssize");
		slr = cursym->n_value;
		printf("sbr %x slr %x\n", sbr, slr);
		lookup("_masterpaddr");
		physrw(fcor, KVTOPH(cursym->n_value), &masterpcbb, 1);
		masterpcbb = (masterpcbb&PG_PFNUM)*NBPG;
		getpcb();
		findstackframe();
		return;
	}
	if (read(fcor, (char *)&u, ctob(UPAGES))!=ctob(UPAGES) ||
	   !INUDOT(u.u_pcb.pcb_ksp) || !INSTACK(u.u_pcb.pcb_usp)) {
		datmap.e1 = MAXFILE;
		return;
	}
	signo = u.u_arg[0];
	sigcode = u.u_code;
	filhdr.a_text = ctob(u.u_tsize);
	filhdr.a_data = ctob(u.u_dsize);
	stksiz = ctob(u.u_ssize);
	switch (filhdr.a_magic) {

	case OMAGIC:
		datmap.b1 = 0;
		datmap.e1 = filhdr.a_text+filhdr.a_data;
		datmap.f2 = ctob(UPAGES) + datmap.e1;
		break;

	case NMAGIC:
	case ZMAGIC:
		datmap.b1 = round(filhdr.a_text, PAGSIZ);
		datmap.e1 = datmap.b1 + filhdr.a_data;
		datmap.f2 = ctob(UPAGES) + filhdr.a_data;
		break;
	}
	datbas = datmap.b1;
	datmap.f1 = ctob(UPAGES);
	datmap.b2 = MAXSTOR - stksiz;
	datmap.e2 = MAXSTOR;
}
示例#5
0
void
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
    uint32_t *intrpc)
{
	int depth = 0;
	register_t sp;
	vm_offset_t callpc;
	pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;

	if (intrpc != 0)
		pcstack[depth++] = (pc_t) intrpc;

	aframes++;

	sp = dtrace_getfp();

	while (depth < pcstack_limit) {
		if (!INKERNEL((long) sp))
			break;

		callpc = *(uintptr_t *)(sp + RETURN_OFFSET);

		if (!INKERNEL(callpc))
			break;

		if (aframes > 0) {
			aframes--;
			if ((aframes == 0) && (caller != 0)) {
				pcstack[depth++] = caller;
			}
		}
		else {
			pcstack[depth++] = callpc;
		}

		sp = *(uintptr_t*)sp;
	}

	for (; depth < pcstack_limit; depth++) {
		pcstack[depth] = 0;
	}
}
示例#6
0
db_sym_t
db_frame_info(long *frame, db_addr_t callpc, const char **namep,
	      db_expr_t *offp, int *is_trap, int *nargp)
{
	db_expr_t	offset;
	db_sym_t	sym;
	int narg;
	const char *name;

	sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
	db_symbol_values(sym, &name, NULL);
	if (sym == (db_sym_t)0)
		return (db_sym_t)0;

	*is_trap = NONE;
	narg = 0;

	if (INKERNEL((long)frame) && name) {
		/*
		 * XXX traps should be based off of the Xtrap*
		 * locations rather than on trap, since some traps
		 * (e.g., npxdna) don't go through trap()
		 */
		if (!strcmp(name, "trap")) {
			*is_trap = TRAP;
			narg = 0;
		} else if (!strcmp(name, "syscall_plain") ||
		           !strcmp(name, "syscall_fancy")) {
			*is_trap = SYSCALL;
			narg = 0;
		} else if (name[0] == 'X') {
			if (!strncmp(name, "Xintr", 5) ||
			    !strncmp(name, "Xresume", 7) ||
			    !strncmp(name, "Xstray", 6) ||
			    !strncmp(name, "Xhold", 5) ||
			    !strncmp(name, "Xrecurse", 8) ||
			    !strcmp(name, "Xdoreti") ||
			    !strncmp(name, "Xsoft", 5)) {
				*is_trap = INTERRUPT;
				narg = 0;
			}
		}
	}

	if (offp != NULL)
		*offp = offset;
	if (nargp != NULL)
		*nargp = narg;
	if (namep != NULL)
		*namep = name;
	return sym;
}
示例#7
0
static int
dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
{
	ASSERT(INKERNEL(kaddr) && kaddr + size >= kaddr);

	if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) {
		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
		cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
		return (0);
	}

	return (1);
}
示例#8
0
static void
stack_capture(struct stack *st, u_int32_t *frame)
{
#if !defined(__ARM_EABI__) && !defined(__clang__)
	vm_offset_t callpc;

	while (INKERNEL(frame)) {
		callpc = frame[FR_SCP];
		if (stack_put(st, callpc) == -1)
			break;
		frame = (u_int32_t *)(frame[FR_RFP]);
	}
#endif
}
示例#9
0
static void
stack_capture(struct stack *st, u_int32_t *frame)
{
	vm_offset_t callpc;

	stack_zero(st);
	while (1) {
		if (!INKERNEL(frame))
			break;
		callpc = frame[FR_SCP];
		if (stack_put(st, callpc) == -1)
			break;
		frame = (u_int32_t *)(frame[FR_RFP]);
	}
}
示例#10
0
int
unwind_frame(struct unwind_state *frame)
{
	uint64_t fp;

	fp = frame->fp;

	if (!INKERNEL(fp))
		return (-1);

	frame->sp = fp;
	frame->fp = *(uint64_t *)(fp - 16);
	frame->pc = *(uint64_t *)(fp - 8) - 4;

	return (0);
}
示例#11
0
void
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, uint32_t *intrpc)
{
	int depth = 0;
	uintptr_t ebp;
	struct frame *frame;
	uintptr_t callpc;
	pc_t caller = (pc_t) CPU[KeGetCurrentProcessorNumber()].cpu_dtrace_caller;
	CONTEXT Context;
#if defined(__i386__) || !defined(windows)
	thread_t *td = curthread;
	
	if (intrpc != 0)
		pcstack[depth++] = (pc_t) intrpc;
		
	aframes++;
	ebp = td->ebp;

	frame = (struct frame *)ebp;
	while (depth < pcstack_limit) {
		if ((uintptr_t)frame < td->klimit || (uintptr_t) ((char *) frame - sizeof(struct frame)) >= td->kbase)
			break;

		callpc = frame->f_retaddr;
		
		if (!INKERNEL(callpc))
			break;

		if (aframes > 0) {
			aframes--;
			if ((aframes == 0) && (caller != 0)) {
				pcstack[depth++] = caller;
			}
		}
		else {
			pcstack[depth++] = callpc;
		}

		frame = frame->f_frame;
	}
#else // windows and amd64
 	depth += RtlCaptureStackBackTrace(aframes, pcstack_limit, (PVOID) pcstack, NULL);
#endif
	for (; depth < pcstack_limit; depth++) {
		pcstack[depth] = 0;
	}
}
示例#12
0
int
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
    struct trapframe *tf)
{
	int frames = 0;
	uintptr_t *sp;

	cc[frames++] = PMC_TRAPFRAME_TO_PC(tf);
	sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf);

	for (frames = 1; frames < maxsamples; frames++) {
		if (!INKERNEL(sp))
			break;
		cc[frames++] = sp[1];
		sp = (uintptr_t *)*sp;
	}
	return (frames);
}
示例#13
0
static void
kgdb_set_tid_cmd (char *arg, int from_tty)
{
	CORE_ADDR addr;
	struct kthr *thr;

	if (!arg)
		error_no_arg ("TID or thread address for the new context");

	addr = (CORE_ADDR) parse_and_eval_address (arg);

	if (kvm != NULL && INKERNEL (addr)) {
		thr = kgdb_thr_lookup_taddr(addr);
		if (thr == NULL)
			error("invalid thread address");
		addr = thr->tid;
	}
	kgdb_switch_to_thread(addr);
}
示例#14
0
int
dtrace_getstackdepth(int aframes)
{
	int depth = 0;
	struct frame *frame;
	uintptr_t ebp;
	uintptr_t callpc;
	thread_t *td = curthread;
#if defined(windows)
	int pcstack_limit = 100;
	uint64_t pcstack[100];
#endif
	ebp = td->ebp;
	frame = (struct frame *)ebp;
	depth++;
	
#ifdef __amd64
	depth += RtlCaptureStackBackTrace(0, pcstack_limit, (PVOID) pcstack, NULL);
#else
	for(;;) {
		if ((uintptr_t)frame < td->klimit || 
		    (uintptr_t) ((char *) frame - sizeof(struct frame)) >= td->kbase)
			break;
		depth++;
		callpc = frame->f_retaddr;
		
		if (!INKERNEL(callpc))
			break;

		frame = frame->f_frame;
	}
#endif
	if (depth < aframes)
		return 0;
	else
		return depth - aframes;
}
示例#15
0
setsym()
{
	off_t loc;
	struct exec hdr;
	register struct nlist *sp;
	int ssiz;
	char *strtab;

	fsym = getfile(symfil, 1);
	txtmap.ufd = fsym;
	if (read(fsym, (char *)&hdr, sizeof hdr) != sizeof hdr ||
	    N_BADMAG(hdr)) {
		txtmap.e1 = MAXFILE;
		return;
	}
	filhdr = hdr;
	loc = filhdr.a_text+filhdr.a_data;
	txtmap.f1 = txtmap.f2 = N_TXTOFF(filhdr);
	txtmap.b1 = 0;
	switch (filhdr.a_magic) {

	case OMAGIC:
		txtmap.b1 = txtmap.e1 = 0;
		txtmap.b2 = datbas = 0;
		txtmap.e2 = loc;
		break;

	case ZMAGIC:
	case NMAGIC:
		txtmap.e1 = filhdr.a_text;
		txtmap.b2 = datbas = round(filhdr.a_text, PAGSIZ);
		txtmap.e2 = datbas + filhdr.a_data;
		txtmap.f2 += txtmap.e1;
	}
	loc = N_SYMOFF(filhdr);
	symtab = (struct nlist *) malloc(filhdr.a_syms);
	esymtab = &symtab[filhdr.a_syms / sizeof (struct nlist)];
	if (symtab == NULL)
		goto nospac;
	lseek(fsym, loc, L_SET);
	if (filhdr.a_syms == 0)
		goto nosymt;
	/* SHOULD SQUISH OUT STABS HERE!!! */
	if (read(fsym, symtab, filhdr.a_syms) != filhdr.a_syms)
		goto readerr;
	if (read(fsym, &ssiz, sizeof (ssiz)) != sizeof (ssiz))
		goto oldfmt;
	strtab = (char *) malloc(ssiz);
	if (strtab == 0)
		goto nospac;
	*(int *)strtab = ssiz;
	ssiz -= sizeof (ssiz);
	if (read(fsym, strtab + sizeof (ssiz), ssiz) != ssiz)
		goto readerr;
	for (sp = symtab; sp < esymtab; sp++)
		if (sp->n_strx)
			/* SHOULD PERFORM RANGE CHECK HERE */
			sp->n_un.n_name = strtab + sp->n_un.n_strx;
nosymt:
	if (INKERNEL(filhdr.a_entry)) {
		txtmap.b1 += KERNOFF;
		txtmap.e1 += KERNOFF;
		txtmap.b2 += KERNOFF;
		txtmap.e2 += KERNOFF;
	}
	return;
readerr:
	printf("Error reading symbol|string table\n");
	exit(1);
nospac:
	printf("Not enough space for symbol|string table\n");
	exit(1);
oldfmt:
	printf("Old format a.out - no string table\n");
	exit(1);
}
示例#16
0
void
db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count,
    char *modif, int (*pr)(const char *, ...))
{
	struct x86_64_frame *frame, *lastframe;
	long		*argp;
	db_addr_t	callpc;
	int		is_trap = 0;
	boolean_t	kernel_only = TRUE;
	boolean_t	trace_thread = FALSE;

#if 0
	if (!db_trace_symbols_found)
		db_find_trace_symbols();
#endif

	{
		char *cp = modif;
		char c;

		while ((c = *cp++) != 0) {
			if (c == 't')
				trace_thread = TRUE;
			if (c == 'u')
				kernel_only = FALSE;
		}
	}

	if (!have_addr) {
		frame = (struct x86_64_frame *)ddb_regs.tf_rbp;
		callpc = (db_addr_t)ddb_regs.tf_rip;
	} else {
#if 0
		if (trace_thread) {
			struct proc *p;
			struct user *u;
			struct lwp *l;
			(*pr)("trace: pid %d ", (int)addr);
			p = pfind(addr);
			if (p == NULL) {
				(*pr)("not found\n");
				return;
			}
			l = proc_representative_lwp(p);
			if (!(l->l_flag&L_INMEM)) {
				(*pr)("swapped out\n");
				return;
			}
			u = l->l_addr;
			frame = (struct x86_64_frame *) u->u_pcb.pcb_rbp;
			(*pr)("at %p\n", frame);
		} else
#endif
			frame = (struct x86_64_frame *)addr;
		callpc = (db_addr_t)
			 db_get_value((db_addr_t)&frame->f_retaddr, 8, FALSE);
		frame = (struct x86_64_frame *)frame->f_frame;
	}

	lastframe = 0;
	while (count && frame != 0) {
		int		narg;
		char *	name;
		db_expr_t	offset;
		db_sym_t	sym;
#define MAXNARG	16
		char	*argnames[MAXNARG], **argnp = NULL;

		sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
		db_symbol_values(sym, &name, NULL);

		if (lastframe == 0 && sym == NULL) {
			/* Symbol not found, peek at code */
			long	instr = db_get_value(callpc, 8, FALSE);

			offset = 1;
			if ((instr & 0x00ffffff) == 0x00e58955 ||
					/* enter: pushl %ebp, movl %esp, %ebp */
			    (instr & 0x0000ffff) == 0x0000e589
					/* enter+1: movl %esp, %ebp */) {
				offset = 0;
			}
		}
		if (INKERNEL(frame) && name) {
#ifdef __ELF__
			if (!strcmp(name, "trap")) {
				is_trap = TRAP;
			} else if (!strcmp(name, "syscall")) {
				is_trap = SYSCALL;
			} else if (name[0] == 'X') {
				if (!strncmp(name, "Xintr", 5) ||
				    !strncmp(name, "Xresume", 7) ||
				    !strncmp(name, "Xstray", 6) ||
				    !strncmp(name, "Xhold", 5) ||
				    !strncmp(name, "Xrecurse", 8) ||
				    !strcmp(name, "Xdoreti") ||
				    !strncmp(name, "Xsoft", 5)) {
					is_trap = INTERRUPT;
				} else
					goto normal;
			} else
				goto normal;
			narg = 0;
#else
			if (!strcmp(name, "_trap")) {
				is_trap = TRAP;
			} else if (!strcmp(name, "_syscall")) {
				is_trap = SYSCALL;
			} else if (name[0] == '_' && name[1] == 'X') {
				if (!strncmp(name, "_Xintr", 6) ||
				    !strncmp(name, "_Xresume", 8) ||
				    !strncmp(name, "_Xstray", 7) ||
				    !strncmp(name, "_Xhold", 6) ||
				    !strncmp(name, "_Xrecurse", 9) ||
				    !strcmp(name, "_Xdoreti") ||
				    !strncmp(name, "_Xsoft", 6)) {
					is_trap = INTERRUPT;
				} else
					goto normal;
			} else
				goto normal;
			narg = 0;
#endif /* __ELF__ */
		} else {
		normal:
			is_trap = NONE;
			narg = MAXNARG;
			if (db_sym_numargs(sym, &narg, argnames))
				argnp = argnames;
			else
				narg = db_numargs(frame);
		}

		(*pr)("%s(", name);

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/*
			 * We have a breakpoint before the frame is set up
			 * Use %esp instead
			 */
			argp = &((struct x86_64_frame *)(ddb_regs.tf_rsp-8))->f_arg0;
		} else {
			argp = &frame->f_arg0;
		}

		while (narg) {
			if (argnp)
				(*pr)("%s=", *argnp++);
			(*pr)("%lx", db_get_value((db_addr_t)argp, 8, FALSE));
			argp++;
			if (--narg != 0)
				(*pr)(",");
		}
		(*pr)(") at ");
		db_printsym(callpc, DB_STGY_PROC, pr);
		(*pr)("\n");

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/* Frame really belongs to next callpc */
			lastframe = (struct x86_64_frame *)(ddb_regs.tf_rsp-8);
			callpc = (db_addr_t)
				 db_get_value((db_addr_t)&lastframe->f_retaddr,
				    8, FALSE);
			continue;
		}

		lastframe = frame;
		db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap, pr);

		if (frame == 0) {
			/* end of chain */
			break;
		}
		if (INKERNEL(frame)) {
			/* staying in kernel */
			if (frame <= lastframe) {
				(*pr)("Bad frame pointer: %p\n", frame);
				break;
			}
		} else if (INKERNEL(lastframe)) {
			/* switch from user to kernel */
			if (kernel_only) {
				(*pr)("end of kernel\n");
				break;	/* kernel stack only */
			}
		} else {
			/* in user */
			if (frame <= lastframe) {
				(*pr)("Bad user frame pointer: %p\n",
					  frame);
				break;
			}
		}
		--count;
	}
	(*pr)("end trace frame: 0x%lx, count: %d\n", frame, count);

	if (count && is_trap != NONE) {
		db_printsym(callpc, DB_STGY_XTRN, pr);
		(*pr)(":\n");
	}
}
示例#17
0
void
db_stack_trace_print(db_expr_t addr, bool have_addr,
		     db_expr_t count, const char *modif,
		     void (*pr)(const char *, ...))
{
	struct frame	*frame, *prevframe;
	db_addr_t	pc;
	bool		kernel_only = true;
	bool		trace_thread = false;
	bool		lwpaddr = false;
	const char	*cp = modif;
	char		c;

	if (ddb_cpuinfo == NULL)
		ddb_cpuinfo = curcpu();

	while ((c = *cp++) != 0) {
		if (c == 'a') {
			lwpaddr = true;
			trace_thread = true;
		}
		if (c == 't')
			trace_thread = true;
		if (c == 'u')
			kernel_only = false;
	}

	if (!have_addr) {
		frame = (struct frame *)DDB_TF->tf_out[6];
		pc = DDB_TF->tf_pc;
	} else {
		if (trace_thread) {
			struct proc *p;
			struct user *u;
			struct lwp *l;
			if (lwpaddr) {
				l = (struct lwp *)addr;
				p = l->l_proc;
				(*pr)("trace: pid %d ", p->p_pid);
			} else {
				(*pr)("trace: pid %d ", (int)addr);
				p = p_find(addr, PFIND_LOCKED);
				if (p == NULL) {
					(*pr)("not found\n");
					return;
				}
				l = LIST_FIRST(&p->p_lwps);
				KASSERT(l != NULL);
			}
			(*pr)("lid %d ", l->l_lid);
			if ((l->l_flag & LW_INMEM) == 0) {
				(*pr)("swapped out\n");
				return;
			}
			u = l->l_addr;
			frame = (struct frame *)u->u_pcb.pcb_sp;
			pc = u->u_pcb.pcb_pc;
			(*pr)("at %p\n", frame);
		} else {
			frame = (struct frame *)addr;
			pc = 0;
		}
	}

	while (count--) {
		int		i;
		db_expr_t	offset;
		const char	*name;
		db_addr_t	prevpc;

#define FR(framep,field) (INKERNEL(framep)			\
				? (u_int)(framep)->field	\
				: fuword(&(framep)->field))

		/* Fetch return address and arguments frame */
		prevpc = (db_addr_t)FR(frame, fr_pc);
		prevframe = (struct frame *)FR(frame, fr_fp);

		/*
		 * Switch to frame that contains arguments
		 */
		if (prevframe == NULL || (!INKERNEL(prevframe) && kernel_only))
			return;

		if ((ONINTSTACK(frame) && !ONINTSTACK(prevframe)) ||
		    (INKERNEL(frame) && !INKERNEL(prevframe))) {
			/* We're crossing a trap frame; pc = %l1 */
			prevpc = (db_addr_t)FR(frame, fr_local[1]);
		}

		name = NULL;
		if (INKERNEL(pc))
			db_find_sym_and_offset(pc, &name, &offset);
		if (name == NULL)
			(*pr)("0x%lx(", pc);
		else
			(*pr)("%s(", name);

		/*
		 * Print %i0..%i5, hope these still reflect the
		 * actual arguments somewhat...
		 */
		for (i = 0; i < 6; i++)
			(*pr)("0x%x%s", FR(frame, fr_arg[i]),
				(i < 5) ? ", " : ") at ");
		if (INKERNEL(prevpc))
			db_printsym(prevpc, DB_STGY_PROC, pr);
		else
			(*pr)("0x%lx", prevpc);
		(*pr)("\n");

		pc = prevpc;
		frame = prevframe;
	}
}
示例#18
0
size_t
md_stack_capture_curthread(caddr_t *pcs, size_t size)
{
        struct trapframe *tf = curthread->td_intr_frame;
	pmap_t pmap = vmspace_pmap(curthread->td_proc->p_vmspace);
	
        size_t num_kstacks = 0, num_ustacks = 0;

#if SAMPLE_DEBUG > 2
	printf("%s(%d):  curthread pid %u, tid %u, name %s\n", __FUNCTION__, __LINE__, curthread->td_proc->p_pid, curthread->td_tid, curthread->td_name);
#endif
	
        if (tf == NULL) {
#if SAMPLE_DEBUG > 5
		printf("%s(%d):  intr frame is NULL?\n", __FUNCTION__, __LINE__);
#endif
//		tf = curthread->td_frame;
		/*
		 * I'm not sure what this means.  This should be done via interrupt,
		 * so if curthread wasn't interrupted, then I don't think we can get
		 * anything here?  Please tell me what I'm doing wrong.
		 */
		return 0;
	}

        if (!TRAPF_USERMODE(tf)) {
                // Start with kernel mode
                unsigned long callpc;
                struct amd64_frame *frame;

                frame = (struct amd64_frame*)tf->tf_rbp;

                while (num_kstacks < size) {
                        if (!INKERNEL((long)frame))
                                break;
                        callpc = frame->f_retaddr;
                        if (!INKERNEL(callpc))
                                break;
                        pcs[num_kstacks++] = (caddr_t)callpc;
                        if (frame->f_frame <= frame ||
                            (vm_offset_t)frame->f_frame >= (vm_offset_t)tf->tf_rbp + KSTACK_PAGES * PAGE_SIZE)
                                break;
                        frame = frame->f_frame;
                }
                tf = curthread->td_frame;
        }
        if (TRAPF_USERMODE(tf)) {
                caddr_t *start_pc = pcs + num_kstacks;
                struct amd64_frame frame;

#if SAMPLE_DEBUG > 3
		printf("%s(%d):  doing user mode crawl\n", __FUNCTION__, __LINE__);
#endif
                frame.f_frame = (struct amd64_frame*)tf->tf_rbp;
                if (tf != curthread->td_intr_frame) {
                        start_pc[num_ustacks++] = (caddr_t)tf->tf_rip;
                }
                while ((num_kstacks + num_ustacks) < size) {
                        void *bp = frame.f_frame;
			/*
			 * The calls to GET_WORD replace the non-functional:
			 * copyin_nofault((void*)frame.f_frame, &frame, sizeof(frame));
			 */
			
			frame.f_frame = (struct amd64_frame*)GET_WORD(pmap, (caddr_t)frame.f_frame);
			if (frame.f_frame == 0) {
#if SAMPLE_DEBUG > 4
				printf("%s(%d):  %s:  frame is 0\n", __FUNCTION__, __LINE__, curthread->td_name);
#endif
				break;
			}
			frame.f_retaddr = (long)GET_WORD(pmap, (caddr_t)frame.f_frame + offsetof(struct amd64_frame, f_retaddr));
			if (frame.f_retaddr == 0) {
#if SAMPLE_DEBUG > 4
				printf("%s(%d):  %s:  retaddr from frame %p is 0\n", __FUNCTION__, __LINE__, curthread->td_name, (void*)frame.f_frame);
#endif
				break;
			}
#if SAMPLE_DEBUG > 2
			printf("%s(%d):  f_frame = %ld, f_retaddr = %ld\n", __FUNCTION__, __LINE__, (long)frame.f_frame, (long)frame.f_retaddr);
#endif
			start_pc[num_ustacks++] = (caddr_t)frame.f_retaddr;
			if ((void*)frame.f_frame < bp) {
				break;
			}
                }
        } else {
示例#19
0
void
db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count,
    char *modif, int (*pr)(const char *, ...))
{
	struct callframe *frame, *lastframe;
	long		*argp, *arg0;
	db_addr_t	callpc;
	int		is_trap = 0;
	boolean_t	kernel_only = TRUE;
	boolean_t	trace_proc = FALSE;

	{
		char *cp = modif;
		char c;

		while ((c = *cp++) != 0) {
			if (c == 'p')
				trace_proc = TRUE;
			if (c == 'u')
				kernel_only = FALSE;
		}
	}

	if (!have_addr) {
		frame = (struct callframe *)ddb_regs.tf_rbp;
		callpc = (db_addr_t)ddb_regs.tf_rip;
	} else {
		if (trace_proc) {
			struct proc *p = pfind((pid_t)addr);
			if (p == NULL) {
				(*pr) ("db_trace.c: process not found\n");
				return;
			}
			frame = (struct callframe *)p->p_addr->u_pcb.pcb_rbp;
		} else {
			frame = (struct callframe *)addr;
		}
		callpc = (db_addr_t)
			 db_get_value((db_addr_t)&frame->f_retaddr, 8, FALSE);
		frame = (struct callframe *)frame->f_frame;
	}

	lastframe = 0;
	while (count && frame != 0) {
		int		narg;
		char *	name;
		db_expr_t	offset;
		db_sym_t	sym;

		sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
		db_symbol_values(sym, &name, NULL);

		if (lastframe == 0 && sym == NULL) {
			/* Symbol not found, peek at code */
			long	instr = db_get_value(callpc, 8, FALSE);

			offset = 1;
			if ((instr & 0x00ffffff) == 0x00e58955 ||
					/* enter: pushl %ebp, movl %esp, %ebp */
			    (instr & 0x0000ffff) == 0x0000e589
					/* enter+1: movl %esp, %ebp */) {
				offset = 0;
			}
		}
		if (INKERNEL(callpc) && name) {
			if (!strcmp(name, "trap")) {
				is_trap = TRAP;
			} else if (!strcmp(name, "ast")) {
				is_trap = AST;
			} else if (!strcmp(name, "syscall")) {
				is_trap = SYSCALL;
			} else if (name[0] == 'X') {
				if (!strncmp(name, "Xintr", 5) ||
				    !strncmp(name, "Xresume", 7) ||
				    !strncmp(name, "Xrecurse", 8) ||
				    !strcmp(name, "Xdoreti") ||
				    !strncmp(name, "Xsoft", 5)) {
					is_trap = INTERRUPT;
				} else
					goto normal;
			} else
				goto normal;
			narg = 0;
		} else {
		normal:
			is_trap = NONE;
			narg = db_numargs(frame);
		}

		(*pr)("%s(", name);

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/*
			 * We have a breakpoint before the frame is set up
			 * Use %rsp instead
			 */
			arg0 =
			    &((struct callframe *)(ddb_regs.tf_rsp-8))->f_arg0;
		} else {
			arg0 = &frame->f_arg0;
		}

		for (argp = arg0; narg > 0; ) {
			(*pr)("%lx", db_get_value((db_addr_t)argp, 8, FALSE));
			argp++;
			if (--narg != 0)
				(*pr)(",");
		}
		(*pr)(") at ");
		db_printsym(callpc, DB_STGY_PROC, pr);
		(*pr)("\n");

		if (lastframe == 0 && offset == 0 && !have_addr && !is_trap) {
			/* Frame really belongs to next callpc */
			lastframe = (struct callframe *)(ddb_regs.tf_rsp-8);
			callpc = (db_addr_t)
				 db_get_value((db_addr_t)&lastframe->f_retaddr,
				    8, FALSE);
			continue;
		}

		if (is_trap == INTERRUPT) {
			/*
			 * Interrupt routines don't update %rbp, so it still
			 * points to the frame that was interrupted.  Pull
			 * back to just above lastframe so we can find the
			 * trapframe as with syscalls and traps.
			 */
			frame = (struct callframe *)&lastframe->f_retaddr;
			arg0 = &frame->f_arg0;
		}

		lastframe = frame;
		db_nextframe(&frame, &callpc, arg0, is_trap, pr);

		if (frame == 0) {
			/* end of chain */
			break;
		}
		if (INKERNEL(frame)) {
			/* staying in kernel */
			if (frame <= lastframe) {
				(*pr)("Bad frame pointer: %p\n", frame);
				break;
			}
		} else if (INKERNEL(lastframe)) {
			/* switch from user to kernel */
			if (kernel_only) {
				(*pr)("end of kernel\n");
				break;	/* kernel stack only */
			}
		} else {
			/* in user */
			if (frame <= lastframe) {
				(*pr)("Bad user frame pointer: %p\n",
					  frame);
				break;
			}
		}
		--count;
	}
	(*pr)("end trace frame: 0x%lx, count: %d\n", frame, count);

	if (count && is_trap != NONE) {
		db_printsym(callpc, DB_STGY_XTRN, pr);
		(*pr)(":\n");
	}
}
示例#20
0
void
db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
		     const char *modif, void (*pr)(const char *, ...))
{
	long *frame, *lastframe;
	long *retaddr, *arg0;
	long		*argp;
	db_addr_t	callpc;
	int		is_trap;
	bool		kernel_only = true;
	bool		trace_thread = false;
	bool		lwpaddr = false;

#if 0
	if (!db_trace_symbols_found)
		db_find_trace_symbols();
#endif

	{
		const char *cp = modif;
		char c;

		while ((c = *cp++) != 0) {
			if (c == 'a') {
				lwpaddr = true;
				trace_thread = true;
			}
			if (c == 't')
				trace_thread = true;
			if (c == 'u')
				kernel_only = false;
		}
	}

	if (!have_addr) {
		frame = (long *)ddb_regs.tf_rbp;
		callpc = (db_addr_t)ddb_regs.tf_rip;
	} else {
		if (trace_thread) {
			struct proc *p;
			struct user *u;
			struct lwp *l;
			if (lwpaddr) {
				l = (struct lwp *)addr;
				p = l->l_proc;
				(*pr)("trace: pid %d ", p->p_pid);
			} else {
				(*pr)("trace: pid %d ", (int)addr);
				p = p_find(addr, PFIND_LOCKED);
				if (p == NULL) {
					(*pr)("not found\n");
					return;
				}
				l = LIST_FIRST(&p->p_lwps);
				KASSERT(l != NULL);
			}
			(*pr)("lid %d ", l->l_lid);
			if (!(l->l_flag & LW_INMEM)) {
				(*pr)("swapped out\n");
				return;
			}
			u = l->l_addr;
			if (p == curproc && l == curlwp) {
				frame = (long *)ddb_regs.tf_rbp;
				callpc = (db_addr_t)ddb_regs.tf_rip;
				(*pr)("at %p\n", frame);
			} else {
				frame = (long *)u->u_pcb.pcb_rbp;
				callpc = (db_addr_t)
				    db_get_value((long)(frame + 1), 8, false);
				(*pr)("at %p\n", frame);
				frame = (long *)*frame; /* XXXfvdl db_get_value? */
			}
		} else {
			frame = (long *)addr;
			callpc = (db_addr_t)
			    db_get_value((long)(frame + 1), 8, false);
			frame = (long *)*frame; /* XXXfvdl db_get_value? */
		}
	}
	retaddr = frame + 1;
	arg0 = frame + 2;

	lastframe = 0;
	while (count && frame != 0) {
		int		narg;
		const char *	name;
		db_expr_t	offset;
		db_sym_t	sym;
		char	*argnames[16], **argnp = NULL;
		db_addr_t	lastcallpc;

		name = "?";
		is_trap = NONE;
		offset = 0;
		sym = db_frame_info(frame, callpc, &name, &offset, &is_trap,
				    &narg);

		if (lastframe == 0 && sym == (db_sym_t)0) {
			/* Symbol not found, peek at code */
			u_long	instr = db_get_value(callpc, 4, false);

			offset = 1;
			if (instr  == 0xe5894855 ||
					/* enter: pushq %rbp, movq %rsp, %rbp */
			    (instr & 0x00ffffff) == 0x0048e589
					/* enter+1: movq %rsp, %rbp */) {
				offset = 0;
			}
		}

		if (is_trap == NONE) {
			if (db_sym_numargs(sym, &narg, argnames))
				argnp = argnames;
			else
				narg = db_numargs(frame);
		}

		(*pr)("%s(", name);

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/*
			 * We have a breakpoint before the frame is set up
			 * Use %rsp instead
			 */
			argp = &((struct x86_64_frame *)(ddb_regs.tf_rsp-8))->f_arg0;
		} else {
			argp = frame + 2;
		}

		while (narg) {
			if (argnp)
				(*pr)("%s=", *argnp++);
			(*pr)("%lx", db_get_value((long)argp, 8, false));
			argp++;
			if (--narg != 0)
				(*pr)(",");
		}
		(*pr)(") at ");
		db_printsym(callpc, DB_STGY_PROC, pr);
		(*pr)("\n");

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/* Frame really belongs to next callpc */
			struct x86_64_frame *fp = (void *)(ddb_regs.tf_rsp-8);

			lastframe = (long *)fp;
			callpc = (db_addr_t)
			    db_get_value((db_addr_t)&fp->f_retaddr, 8, false);
			continue;
		}

		lastframe = frame;
		lastcallpc = callpc;
		if (!db_nextframe(&frame, &retaddr, &arg0,
		   &callpc, frame + 2, is_trap, pr))
			break;

		if (INKERNEL((long)frame)) {
			/* staying in kernel */
			if (frame < lastframe ||
			    (frame == lastframe && callpc == lastcallpc)) {
				(*pr)("Bad frame pointer: %p\n", frame);
				break;
			}
		} else if (INKERNEL((long)lastframe)) {
			/* switch from user to kernel */
			if (kernel_only)
				break;	/* kernel stack only */
		} else {
			/* in user */
			if (frame <= lastframe) {
				(*pr)("Bad user frame pointer: %p\n",
					  frame);
				break;
			}
		}
		--count;
	}

	if (count && is_trap != NONE) {
		db_printsym(callpc, DB_STGY_XTRN, pr);
		(*pr)(":\n");
	}
}