* Accessing the user stack inside system call service routine @ 2002-06-13 7:43 Steffen Rumler 2002-06-13 11:10 ` Neil Horman 0 siblings, 1 reply; 7+ messages in thread From: Steffen Rumler @ 2002-06-13 7:43 UTC (permalink / raw) To: linuxppc Hello, I want to access/record the user stack within the system call service routine sys_sigsuspend() (arch/ppc/signal.c), in order to debug hanging threads. The user register context is passed to sys_sigsuspend() via the 'struct pt_regs *regs' argument. In this way I can obtain the stack pointer r1 (via regs->gpr[1]) and catch the PPC EABI stack frames. But I see all zeros behind 'regs->gpr[1]' instead of proper stack frames. What is wrong ? How can I access the user stack within a system call service routine (sys_XXX) ? Thank you for help, Steffen -- -------------------------------------------------------------- Steffen Rumler ICN ON PNE SB 4 Siemens AG Hofmannstr. 51 Email: Steffen.Rumler@icn.siemens.de D-81359 Munich Phone: +49 89 722-44061 Germany Fax : +49 89 722-36703 -------------------------------------------------------------- ** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Accessing the user stack inside system call service routine 2002-06-13 7:43 Accessing the user stack inside system call service routine Steffen Rumler @ 2002-06-13 11:10 ` Neil Horman 2002-06-13 14:20 ` Steffen Rumler 0 siblings, 1 reply; 7+ messages in thread From: Neil Horman @ 2002-06-13 11:10 UTC (permalink / raw) To: Steffen Rumler; +Cc: linuxppc Since the process virtual address which are used on the user space stack are not directly available from the context of the kernel, you will need to do some virtual address translation to access teh stack frames you are interested in. I would suggest that you look at the source code for the copy_to_user and copy_from_user functions to see how they access a process address space from kernel space. That will probably start you in the right direction. hope that helps! Neil :) Steffen Rumler wrote: > Hello, > > I want to access/record the user stack within the system call > service routine sys_sigsuspend() (arch/ppc/signal.c), > in order to debug hanging threads. > > The user register context is passed to sys_sigsuspend() via > the 'struct pt_regs *regs' argument. > > In this way I can obtain the stack pointer r1 > (via regs->gpr[1]) and catch the PPC EABI stack frames. > > But I see all zeros behind 'regs->gpr[1]' instead of proper > stack frames. What is wrong ? > > How can I access the user stack within a > system call service routine (sys_XXX) ? > > Thank you for help, > > > Steffen > > -- > > > -------------------------------------------------------------- > > Steffen Rumler > ICN ON PNE SB 4 > Siemens AG > Hofmannstr. 51 Email: Steffen.Rumler@icn.siemens.de > D-81359 Munich Phone: +49 89 722-44061 > Germany Fax : +49 89 722-36703 > > -------------------------------------------------------------- > > -- /****************************************************************** *Neil Horman *Software Engineer *LVL7 Systems *13000 Weston Pkwy. *Cary, NC 27513 *(919)-865-2915 *nhorman@lvl7.com *PGP keyID 0xB5E1020A *http://www.keyserver.net/en *******************************************************************/ ** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Accessing the user stack inside system call service routine 2002-06-13 11:10 ` Neil Horman @ 2002-06-13 14:20 ` Steffen Rumler 2002-06-13 15:11 ` Neil Horman 2002-06-13 21:46 ` Paul Mackerras 0 siblings, 2 replies; 7+ messages in thread From: Steffen Rumler @ 2002-06-13 14:20 UTC (permalink / raw) To: Neil Horman; +Cc: linuxppc > Since the process virtual address which are used on the user space stack are not > directly available from the context of the kernel, you will need to do some > virtual address translation to access teh stack frames you are interested in. I > would suggest that you look at the source code for the copy_to_user and > copy_from_user functions to see how they access a process address space from > kernel space. That will probably start you in the right direction. > hope that helps! > Neil :) > Thank you for the answer. I have not accessed the user space directly. Instead I have just used copy_from_user(): int sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, struct pt_regs *regs) { ... while (1) { current->state = TASK_INTERRUPTIBLE; current->in_suspend = 1; /* XXX my stuff for debugging */ current->user_regs = regs; if(copy_from_user(current->user_stack_xxx, regs->gpr[1], 128)){ printk("\n------------- copy_from_user failed: %d\n", ret); } schedule(); current->in_suspend = 0; /* XXX my stuff for debugging */ current->user_regs = NULL; ... } The copy_from_user() works fine. The printk() message does not appear. Later, when I inspect 'current->user_stack_xxx' (temporary added to struct_task) for all processes with 'current->in_suspend' set, all seems to be zero. I do this check within a kernel module, I can load when the threads are hanging. Steffen -- -------------------------------------------------------------- Steffen Rumler ICN ON PNE SB 4 Siemens AG Hofmannstr. 51 Email: Steffen.Rumler@icn.siemens.de D-81359 Munich Phone: +49 89 722-44061 Germany Fax : +49 89 722-36703 -------------------------------------------------------------- ** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Accessing the user stack inside system call service routine 2002-06-13 14:20 ` Steffen Rumler @ 2002-06-13 15:11 ` Neil Horman 2002-06-13 21:46 ` Paul Mackerras 1 sibling, 0 replies; 7+ messages in thread From: Neil Horman @ 2002-06-13 15:11 UTC (permalink / raw) To: Steffen Rumler; +Cc: linuxppc Ahh, so you had already covered the addressing point. sorry. Well, the next thing that would occur to me is that 128 bytes of all zero's may be ok. I'm not quite sure of the details of the inner workings of the standard C library for this situation, but right before the code in the C library executes a trap instruction to make the reuqested system call, it may append extra data to the last user space stack frame. I know this happens during signal handling. Granted that call stack is transitioning the other way, but you see the same sort of behavior, in which the first "stack frame" is not really a stack frame, but rather a block of data which is removed before a return to the application at the point where it called the library function. I would suggest that you try copying more than 128 bytes to see if you start seeing valid stack frames, or more directly, invistigate the C library code which wraps around the system call in user space to see if it makes and strange manipulations to the stack frame before executing a trap. Good luck! Neil Steffen Rumler wrote: >> Since the process virtual address which are used on the user space stack are not >>directly available from the context of the kernel, you will need to do some >>virtual address translation to access teh stack frames you are interested in. I >>would suggest that you look at the source code for the copy_to_user and >>copy_from_user functions to see how they access a process address space from >>kernel space. That will probably start you in the right direction. >>hope that helps! >>Neil :) >> >> > > Thank you for the answer. > > I have not accessed the user space directly. > Instead I have just used copy_from_user(): > > > int > sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int > p7, > struct pt_regs *regs) > { > ... > while (1) { > > current->state = TASK_INTERRUPTIBLE; > > current->in_suspend = 1; /* XXX my stuff for debugging */ > current->user_regs = regs; > if(copy_from_user(current->user_stack_xxx, regs->gpr[1], 128)){ > > printk("\n------------- copy_from_user failed: %d\n", ret); > } > > schedule(); > > current->in_suspend = 0; /* XXX my stuff for debugging */ > current->user_regs = NULL; > ... > } > > The copy_from_user() works fine. The printk() message does not > appear. > > Later, when I inspect 'current->user_stack_xxx' (temporary > added to struct_task) for all processes with 'current->in_suspend' > set, all seems to be zero. I do this check within a kernel > module, I can load when the threads are hanging. > > Steffen > > -- /****************************************************************** *Neil Horman *Software Engineer *LVL7 Systems *13000 Weston Pkwy. *Cary, NC 27513 *(919)-865-2915 *nhorman@lvl7.com *PGP keyID 0xB5E1020A *http://www.keyserver.net/en *******************************************************************/ ** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Accessing the user stack inside system call service routine 2002-06-13 14:20 ` Steffen Rumler 2002-06-13 15:11 ` Neil Horman @ 2002-06-13 21:46 ` Paul Mackerras 2002-06-13 22:28 ` Frank Rowand 2002-06-19 11:40 ` Steffen Rumler 1 sibling, 2 replies; 7+ messages in thread From: Paul Mackerras @ 2002-06-13 21:46 UTC (permalink / raw) To: Steffen Rumler; +Cc: Neil Horman, linuxppc Steffen Rumler writes: > The copy_from_user() works fine. The printk() message does not > appear. The copy_from_user call looks correct to me. > Later, when I inspect 'current->user_stack_xxx' (temporary > added to struct_task) for all processes with 'current->in_suspend' > set, all seems to be zero. I do this check within a kernel > module, I can load when the threads are hanging. That is indeed very strange. The first word should be non-zero at the very least. Is it possible that your program has in fact trashed its stack? Another thing to try would be to check the contents of current->user_stack_xxx immediately after you copy it to see whether it is all zero at that point. Paul. ** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Accessing the user stack inside system call service routine 2002-06-13 21:46 ` Paul Mackerras @ 2002-06-13 22:28 ` Frank Rowand 2002-06-19 11:40 ` Steffen Rumler 1 sibling, 0 replies; 7+ messages in thread From: Frank Rowand @ 2002-06-13 22:28 UTC (permalink / raw) To: Steffen Rumler; +Cc: linuxppc Paul Mackerras wrote: > > Steffen Rumler writes: > > > The copy_from_user() works fine. The printk() message does not > > appear. > > The copy_from_user call looks correct to me. > > > Later, when I inspect 'current->user_stack_xxx' (temporary > > added to struct_task) for all processes with 'current->in_suspend' > > set, all seems to be zero. I do this check within a kernel > > module, I can load when the threads are hanging. > > That is indeed very strange. The first word should be non-zero at the > very least. Is it possible that your program has in fact trashed its > stack? Another thing to try would be to check the contents of > current->user_stack_xxx immediately after you copy it to see whether > it is all zero at that point. Here is how the Linux Trace Toolkit (LTT) kernel patch searches back through the stack, in the case of a syscall, to find the caller of the library function that resulted in a syscall (for example, the place that printf() was called from, not the place that the resulting syscall was called from in the library). It sounds like you don't need to dig that far back in the calling sequence. Hopefully this example can point you in the right direction. #if (CONFIG_TRACE || CONFIG_TRACE_MODULE) asmlinkage void trace_real_syscall_entry(struct pt_regs * regs) { int use_depth; int use_bounds; int depth = 0; int seek_depth; unsigned long lower_bound; unsigned long upper_bound; unsigned long addr; unsigned long* stack; trace_syscall_entry trace_syscall_event; /* Set the syscall ID */ trace_syscall_event.syscall_id = (uint8_t) regs->gpr[0]; /* Set the address in any case */ trace_syscall_event.address = instruction_pointer(regs); /* Are we in the kernel (This is a kernel thread)? */ if(!user_mode(regs)) /* Don't go digining anywhere */ goto trace_syscall_end; /* Get the trace configuration */ if(trace_get_config(&use_depth, &use_bounds, &seek_depth, (void*)&lower_bound, (void*)&upper_bound) < 0) goto trace_syscall_end; /* Do we have to search for an eip address range */ if((use_depth == 1) || (use_bounds == 1)) { /* Start at the top of the stack (bottom address since stacks grow downward) */ stack = (unsigned long*) regs->gpr[1]; /* Skip over first stack frame as the return address isn't valid */ if(get_user(addr, stack)) goto trace_syscall_end; stack = (unsigned long*) addr; /* Keep on going until we reach the end of the process' stack limit (wherever it may be) */ while(!get_user(addr, stack + 1)) /* "stack + 1", since this is where the IP is */ { /* Does this LOOK LIKE an address in the program */ if((addr > current->mm->start_code) &&(addr < current->mm->end_code)) { /* Does this address fit the description */ if(((use_depth == 1) && (depth == seek_depth)) ||((use_bounds == 1) && (addr > lower_bound) && (addr < upper_bound))) { /* Set the address */ trace_syscall_event.address = addr; /* We're done */ goto trace_syscall_end; } else /* We're one depth more */ depth++; } /* Go on to the next address */ if(get_user(addr, stack)) goto trace_syscall_end; stack = (unsigned long*) addr; } } trace_syscall_end: /* Trace the event */ trace_event(TRACE_EV_SYSCALL_ENTRY, &trace_syscall_event); } -Frank -- Frank Rowand <frank_rowand@mvista.com> MontaVista Software, Inc ** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Accessing the user stack inside system call service routine 2002-06-13 21:46 ` Paul Mackerras 2002-06-13 22:28 ` Frank Rowand @ 2002-06-19 11:40 ` Steffen Rumler 1 sibling, 0 replies; 7+ messages in thread From: Steffen Rumler @ 2002-06-19 11:40 UTC (permalink / raw) To: Paul Mackerras; +Cc: Neil Horman, linuxppc, Frank Rowand > That is indeed very strange. The first word should be non-zero at the > very least. Is it possible that your program has in fact trashed its > stack? Another thing to try would be to check the contents of > current->user_stack_xxx immediately after you copy it to see whether > it is all zero at that point. Thank you all for the answer, it is now working fine. I have basically used the LTT routine to analyze the EABI stack frames, provided by Frank. When I copy the relevant addresses (backchain pointer, saved link register) to separate static buffer and not to the task structure it is working. Steffen -- -------------------------------------------------------------- Steffen Rumler ICN ON PNE SB 4 Siemens AG Hofmannstr. 51 Email: Steffen.Rumler@icn.siemens.de D-81359 Munich Phone: +49 89 722-44061 Germany Fax : +49 89 722-36703 -------------------------------------------------------------- ** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2002-06-19 11:40 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2002-06-13 7:43 Accessing the user stack inside system call service routine Steffen Rumler 2002-06-13 11:10 ` Neil Horman 2002-06-13 14:20 ` Steffen Rumler 2002-06-13 15:11 ` Neil Horman 2002-06-13 21:46 ` Paul Mackerras 2002-06-13 22:28 ` Frank Rowand 2002-06-19 11:40 ` Steffen Rumler
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.