libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libunwind-devel] different stack trace results for direct syscall and l


From: Tanya Gornak
Subject: [Libunwind-devel] different stack trace results for direct syscall and libc
Date: Mon, 8 Feb 2010 17:30:04 +0300

 Hi. I try to unwind stack of a remote process when it is stopped on a syscall.

And I have a problem. I'll explain it on syscall write. I have two examples: one of this calls printf function and another calls write function. And when syscall write happend in printf I got relevant call stack:

00000000b809c424                                  (sp=00000000bfb48400)                                              
00000000b7fb34bf new_do_write+0x4f                (sp=00000000bfb48440)                              
00000000b7fb37d6 _IO_do_write+0x26                (sp=00000000bfb4846c)                                         
00000000b7fb42dd _IO_file_overflow+0xed           (sp=00000000bfb4847c)                                         
00000000b7fb6aaa __overflow+0x4a                  (sp=00000000bfb484a0)                                   
00000000b7faa46b _IO_puts+0x16b                   (sp=00000000bfb484b8)   
00000000080483b6 f+0x12                           (sp=00000000bfb484e0)      
00000000080483c3 g+0xb                            (sp=00000000bfb48500)        
00000000080483d0 main+0xb                         (sp=00000000bfb48510)      
00000000b7f62b86 __libc_start_main+0xe6           (sp=00000000bfb48520)       
0000000008048311 _start+0x21                      (sp=00000000bfb485a0)
    
but when it happend in wirte function I get call stack which contained only main function: 

00000000b804e424 +0xbfef0f18                      (sp=00000000bf87281c)                                
0000000008048504 main+0xb                         (sp=00000000bf872860)                                             
00000000b7f14b86 __libc_start_main+0xe6           (sp=00000000bf872870)                                              
00000000080483e1 _start+0x21                      (sp=00000000bf8728f0)       

P.S. 
Function which I use for unwinding: 

void do_backtrace(pid_t target_pid)
{
  unw_word_t ip, sp, start_ip = 0, off;
  int n = 0, ret;
  unw_proc_info_t pi;
  unw_cursor_t c;
  char buf[512];
  size_t len;
  
  fprintf(stderr, "Target pid is %lu\n", (unsigned long)target_pid);
  
  as = unw_create_addr_space (&_UPT_accessors, 0);
  if (!as)
    panic ("unw_create_addr_space() failed");
   ui = _UPT_create (target_pid);
  
  ret = unw_init_remote (&c, as, ui);
  if (ret < 0)
    panic ("unw_init_remote() failed: ret=%d\n", ret);

  do
    {
      if ((ret = unw_get_reg (&c, UNW_REG_IP, &ip)) < 0
          || (ret = unw_get_reg (&c, UNW_REG_SP, &sp)) < 0)
        panic ("unw_get_reg/unw_get_proc_name() failed: ret=%d\n", ret);

      if (n == 0)
        start_ip = ip;

      buf[0] = '\0';
      if (print_names)
        unw_get_proc_name (&c, buf, sizeof (buf), &off);

      if (off)
            {
              len = strlen (buf);
              if (len >= sizeof (buf) - 32)
                len = sizeof (buf) - 32;
              sprintf (buf + len, "+0x%lx", (unsigned long)off);
            }
          printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp);
        

      if ((ret = unw_get_proc_info (&c, &pi)) < 0)
        panic ("unw_get_proc_info(ip=0x%lx) failed: ret=%d\n", (long) ip, ret);
      else printf ("\tproc=%016lx-%016lx\n\thandler=%lx lsda=%lx\n",
                (long) pi.start_ip, (long) pi.end_ip,
                (long) pi.handler, (long) pi.lsda);

#if UNW_TARGET_IA64
      {
        unw_word_t bsp;

        if ((ret = unw_get_reg (&c, UNW_IA64_BSP, &bsp)) < 0)
          panic ("unw_get_reg() failed: ret=%d\n", ret);
        else  printf (" bsp=%lx", bsp);
      }
#endif
      ret = unw_step (&c);
      if (ret < 0)
        {
          unw_get_reg (&c, UNW_REG_IP, &ip);
          panic ("FAILURE: unw_step() returned %d for ip=%lx (start ip=%lx)\n",
                 ret, (long) ip, (long) start_ip);
        }

      if (++n > 64)
        {
          /* guard against bad unwind info in old libraries... */
          panic ("too deeply nested---assuming bogus unwind (start ip=%lx)\n",
                 (long) start_ip);
          break;
        }
    }
  while (ret > 0);

  if (ret < 0)
    panic ("unwind failed with ret=%d\n", ret);

  printf ("\n\n================\n\n");
  
  _UPT_destroy (ui);
}


Test example which uses printf:

#include <stdio.h>
void f(void){
        printf("Hello libunwind\n");

}
void g(void){
        f();
}
int main(){

        g();
}

Test example which uses write:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>


void func(){
        int pipe;
        char* buffer;
        if( NULL == ( buffer = (char*)malloc( sizeof(char)*5 ) ) )
                perror("Malloc fail with ");
        buffer[0] = 'a';
        if (-1 == (pipe = open("./test.txt", O_WRONLY, 0))){
                perror("Can't open file ");
        }
        write(  pipe,  buffer,  5  );
        close(pipe);

}
int main(int argc, char *argv[]) {

        func();
}

Program which I use to test do_backtrace():

int main(int argc, char* argv[])
{   pid_t child;
    char *str;
    long orig_eax, eax;
    long params[3];
    int status;
    int insyscall = 0;

    child = fork();
    if(child == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execl(argv[1], argv[1], NULL);
    }
    else {
       while(1) {
          wait(&status);
          if(WIFEXITED(status))
              break;
          orig_eax = ptrace(PTRACE_PEEKUSER,
                     child, 4 * ORIG_EAX, NULL);
          if(orig_eax == SYS_write) {
             if(insyscall == 0) {
                /* Syscall entry */
                insyscall = 1;
                printf("Syscall write entry\n");
                }
           else { 
                /* Syscall exit */
                eax = ptrace(PTRACE_PEEKUSER,
                             child, 4 * EAX, NULL);
                    printf("Write returned with %ld\n", eax);
                    insyscall = 0;
                }

            }
            do_backtrace(child);
            ptrace(PTRACE_SYSCALL,
                   child, NULL, NULL);
                                    }
    }
    return 0;
}

Thanks in advance.
Tatiana

reply via email to

[Prev in Thread] Current Thread [Next in Thread]