Ejemplo n.º 1
0
/* This recently started being used in arch-independent code too, as in
 * kernel/sched.c.*/
void show_stack(struct task_struct *task, unsigned long *esp)
{
	unsigned long *stack;
	int i;

	if (esp == NULL) {
		if (task != current && task != NULL) {
			esp = (unsigned long *) KSTK_ESP(task);
		} else {
			esp = (unsigned long *) &esp;
		}
	}

	stack = esp;
	for(i = 0; i < kstack_depth_to_print; i++) {
		if (kstack_end(stack))
			break;
		if (i && ((i % 8) == 0))
			printk("\n       ");
		printk("%08lx ", *stack++);
	}

	printk("Call Trace: \n");
	show_trace(task, esp);
}
Ejemplo n.º 2
0
void
dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
{   uint64_t *pcstack_end = pcstack + pcstack_limit;
    volatile uint8_t *flags =
        (volatile uint8_t *)&cpu_core[cpu_get_id()].cpuc_dtrace_flags;
    unsigned long *sp;
    unsigned long *bos;

    if (*flags & CPU_DTRACE_FAULT)
        return;

    if (pcstack_limit <= 0)
        return;

    *pcstack++ = (uint64_t)current->pid;

    if (pcstack >= pcstack_end)
        return;

    /***********************************************/
    /*   Linux provides a built in function which  */
    /*   is  good  because  stack walking is arch  */
    /*   dependent.            (save_stack_trace)  */
    /*   					       */
    /*   Unfortunately  this is options dependent  */
    /*   (CONFIG_STACKTRACE) so we cannot use it.  */
    /*   And  its  GPL  anyhow, so we cannot copy  */
    /*   it.				       */
    /*   					       */
    /*   Whats worse is that we might be compiled  */
    /*   with a frame pointer (only on x86-32) so  */
    /*   we have three scenarios to handle.	       */
    /***********************************************/

    /***********************************************/
    /*   Ye  gods! The world is an awful place to  */
    /*   live. The target process, may or may not  */
    /*   have   frame  pointers.  In  fact,  some  */
    /*   frames  may have it and some may not (eg  */
    /*   different   libraries  may  be  compiled  */
    /*   differently).			       */
    /*   					       */
    /*   Looks like distro owners dont care about  */
    /*   debuggabiity,   and  give  us  no  frame  */
    /*   pointers.				       */
    /*   					       */
    /*   This  function  is  really important and  */
    /*   useful.  On  modern  Linux  systems, gdb  */
    /*   (and  pstack) contain all the smarts. In  */
    /*   fact,  pstack  is often a wrapper around  */
    /*   gdb  -  i.e. its so complex we cannot do  */
    /*   this.				       */
    /***********************************************/

    /***********************************************/
    /*   Bear  in  mind  that  user stacks can be  */
    /*   megabytes  in  size,  vs  kernel  stacks  */
    /*   which  are  limited  to a few K (4 or 8K  */
    /*   typically).			       */
    /***********************************************/

//	sp = current->thread.rsp;
# if defined(__i386)
    bos = sp = KSTK_ESP(current);
#	define	ALIGN_MASK	3
# else
    /***********************************************/
    /*   KSTK_ESP()  doesnt exist for x86_64 (its  */
    /*   set to -1).			       */
    /***********************************************/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
#  if defined(KSTK_EIP)
    /***********************************************/
    /*   Handle  ARM and more kernel independent,  */
    /*   but might not exist.		       */
    /***********************************************/
    bos = sp = (unsigned long *) KSTK_EIP(current);
#  else
    bos = sp = (unsigned long *) task_pt_regs(current)->sp;
#  endif
#else
    bos = sp = task_pt_regs(current)->rsp;
#endif
#	define	ALIGN_MASK	7
#endif

    /***********************************************/
    /*   Walk  the  stack.  We  cannot  rely on a  */
    /*   frame  pointer  at  each  level,  and we  */
    /*   really  want to avoid probing every word  */
    /*   in  the  stack  - a large stack will eat  */
    /*   cpu  looking at thousands of entries. So  */
    /*   try  and  heuristically see if we have a  */
    /*   likely  frame  pointer  to jump over the  */
    /*   frame,  but, if not, just go one word at  */
    /*   a time.				       */
    /*   					       */
    /*   Try  and be careful we dont walk outside  */
    /*   the  stack  or  walk  backwards  in  the  */
    /*   stack, too.			       */
    /***********************************************/
    {   uintptr_t *spend = sp + 1024;
        struct vm_area_struct *vma = find_vma(current->mm, (unsigned long) sp);
        if (vma)
            spend = (uintptr_t *) (vma->vm_end - sizeof(int *));

        /*printk("xbos=%p %p\n", bos, spend);*/

        /***********************************************/
        /*   Have  you ever looked at the output from  */
        /*   GCC in amd64 mode? Things like:	       */
        /*   					       */
        /*   push %r12				       */
        /*   push %rbp				       */
        /*   					       */
        /*   will make you come out in a cold sweat -  */
        /*   no   way  to  find  the  frame  pointer,  */
        /*   without doing what GDB does (ie read the  */
        /*   DWARF  stack  unwind info). So, for now,  */
        /*   you  get  some  false  positives  in the  */
        /*   output - but we try to be conservative.   */
        /***********************************************/
        while (sp >= bos && sp < spend && validate_ptr(sp)) {
            /*printk("  %p %d: %p %d\n", sp, validate_ptr(sp), sp[0], validate_ptr(sp[0]));*/
            if (validate_ptr((void *) sp[0])) {
                uintptr_t p = sp[-1];
                /***********************************************/
                /*   Try  and  avoid false positives in stack  */
                /*   entries   -   we  want  this  to  be  an  */
                /*   executable instruction.		       */
                /***********************************************/
                if (((unsigned long *) sp[0] < bos || (unsigned long *) sp[0] > spend) &&
                        (vma = find_vma(current->mm, sp[0])) != NULL &&
                        vma->vm_flags & VM_EXEC) {
                    *pcstack++ = sp[0];
                    if (pcstack >= pcstack_end)
                        break;
                }
                if (((int) p & ALIGN_MASK) == 0 && p > (uintptr_t) sp && p < (uintptr_t) spend)
                    sp = (unsigned long *) p;
            }
            sp++;
        }
    }

    /***********************************************/
    /*   Erase  anything  else  in  the buffer to  */
    /*   avoid confusion.			       */
    /***********************************************/
    while (pcstack < pcstack_end)
        *pcstack++ = (pc_t) NULL;
}
Ejemplo n.º 3
0
static int get_stat(int pid, char * buffer)
{
	struct task_struct ** p = get_task(pid);
	unsigned long sigignore=0, sigcatch=0, bit=1, wchan;
	int i,tty_pgrp;
	char state;

	if (!p || !*p)
		return 0;
	if ((*p)->state < 0 || (*p)->state > 5)
		state = '.';
	else
		state = "RSDZTD"[(*p)->state];
	wchan = get_wchan(*p);
	for(i=0; i<32; ++i) {
		switch((int) (*p)->sigaction[i].sa_handler) {
		case 1: sigignore |= bit; break;
		case 0: break;
		default: sigcatch |= bit;
		} bit <<= 1;
	}
	tty_pgrp = (*p)->tty;
	if (tty_pgrp > 0 && tty_table[tty_pgrp])
		tty_pgrp = tty_table[tty_pgrp]->pgrp;
	else
		tty_pgrp = -1;
	return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %u \
%u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d \
%d %d %d %u\n",
		pid,
		(*p)->comm,
		state,
		(*p)->p_pptr->pid,
		(*p)->pgrp,
		(*p)->session,
		(*p)->tty,
		tty_pgrp,
		(*p)->flags,
		(*p)->min_flt,
		(*p)->cmin_flt,
		(*p)->maj_flt,
		(*p)->cmaj_flt,
		(*p)->utime,
		(*p)->stime,
		(*p)->cutime,
		(*p)->cstime,
		(*p)->counter,  /* this is the kernel priority ---
				   subtract 30 in your user-level program. */
		(*p)->priority, /* this is the nice value ---
				   subtract 15 in your user-level program. */
		(*p)->timeout,
		(*p)->it_real_value,
		(*p)->start_time,
		VSIZE((*p),(*p)->kernel_stack_page),
		(*p)->rss, /* you might want to shift this left 3 */
		(*p)->rlim[RLIMIT_RSS].rlim_cur,
		(*p)->start_code,
		(*p)->end_code,
		(*p)->start_stack,
		KSTK_ESP((*p)->kernel_stack_page),
		KSTK_EIP((*p)->kernel_stack_page),
		(*p)->signal,
		(*p)->blocked,
		sigignore,
		sigcatch,
		wchan);
}
Ejemplo n.º 4
0
static int get_stat(int pid, char * buffer)
{
    struct task_struct ** p = get_task(pid), *tsk;
    unsigned long sigignore=0, sigcatch=0, wchan;
    unsigned long vsize, eip, esp;
    long priority, nice;
    int i,tty_pgrp;
    char state;

    if (!p || (tsk = *p) == NULL)
        return 0;
    if (tsk->state < 0 || tsk->state > 5)
        state = '.';
    else
        state = "RSDZTW"[tsk->state];
    vsize = eip = esp = 0;
    if (tsk->mm && tsk->mm != &init_mm) {
        struct vm_area_struct *vma = tsk->mm->mmap;
        while (vma) {
            vsize += vma->vm_end - vma->vm_start;
            vma = vma->vm_next;
        }
        if (tsk->kernel_stack_page) {
            eip = KSTK_EIP(tsk);
            esp = KSTK_ESP(tsk);
        }
    }
    wchan = get_wchan(tsk);
    if (tsk->sig) {
        unsigned long bit = 1;
        for(i=0; i<32; ++i) {
            switch((unsigned long) tsk->sig->action[i].sa_handler) {
            case 0:
                break;
            case 1:
                sigignore |= bit;
                break;
            default:
                sigcatch |= bit;
            }
            bit <<= 1;
        }
    }
    if (tsk->tty)
        tty_pgrp = tsk->tty->pgrp;
    else
        tty_pgrp = -1;

    /* scale priority and nice values from timeslices to -20..20 */
    /* to make it look like a "normal" unix priority/nice value  */
    priority = tsk->counter;
    priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY;
    nice = tsk->priority;
    nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;

    return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
%lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
%lu %lu %lu %lu %lu %lu %lu %lu\n",
                   pid,
                   tsk->comm,
                   state,
                   tsk->p_pptr->pid,
                   tsk->pgrp,
                   tsk->session,
                   tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0,
                   tty_pgrp,
                   tsk->flags,
                   tsk->min_flt,
                   tsk->cmin_flt,
                   tsk->maj_flt,
                   tsk->cmaj_flt,
                   tsk->utime,
                   tsk->stime,
                   tsk->cutime,
                   tsk->cstime,
                   priority,
                   nice,
                   tsk->timeout,
                   tsk->it_real_value,
                   tsk->start_time,
                   vsize,
                   tsk->mm ? tsk->mm->rss : 0, /* you might want to shift this left 3 */
                   tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0,
                   tsk->mm ? tsk->mm->start_code : 0,
                   tsk->mm ? tsk->mm->end_code : 0,
                   tsk->mm ? tsk->mm->start_stack : 0,
                   esp,
                   eip,
                   tsk->signal,
                   tsk->blocked,
                   sigignore,
                   sigcatch,
                   wchan,
                   tsk->nswap,
                   tsk->cnswap);
}