wiki:Dev/KernelHack/COINS/worklog/201110

Version 2 (modified by mitty, 13 years ago) (diff)

--

10/05

trace getpid() syscall with GDB

  • windell57:x86_64 s0711489$ gdb
    (gdb) set logging file gdb.getpid.log
    (gdb) set logging on
    Copying output to gdb.getpid.log.
    (gdb) file vmlinux
    Reading symbols from /home/ugrad/07/s0711489/coursework/KernelHack/linux-2.6.35.14/x86_64/vmlinux...(no debugging symbols found)...done.
    (gdb) b sys_getpid
    Breakpoint 1 at 0xffffffff81048ce4: file kernel/timer.c, line 1344.
    (gdb) target remote localhost:8864
    Remote debugging using localhost:8864
    0xffffffff810097a9 in native_safe_halt ()
        at /home/ugrad/07/s0711489/coursework/KernelHack/linux-2.6.35.14/x86_64/arch/x86/include/asm/irqflags.h:49
    49              asm volatile("sti; hlt": : :"memory");
    (gdb) c
    Continuing.
    
    Breakpoint 1, sys_getpid () at kernel/timer.c:1344
    
  • => attachment:gdb.getpid.log
  • on VM guest
    • s0711489@ubuntu-lucid64:~/coursework/KernelHack/02$ ./getpid
      getpid() -> 2143
      

trace log with source list and print data

  • windell57:x86_64 s0711489$ gdb
    (gdb) file vmlinux
    Reading symbols from /home/ugrad/07/s0711489/coursework/KernelHack/linux-2.6.35.14/x86_64/vmlinux...(no debugging symbols found)...done.
    (gdb) b sys_getpid
    Breakpoint 1 at 0xffffffff81048ce4: file kernel/timer.c, line 1344.
    (gdb) target remote localhost:8864
    Remote debugging using localhost:8864
    0xffffffff810097a9 in native_safe_halt ()
        at /home/ugrad/07/s0711489/coursework/KernelHack/linux-2.6.35.14/x86_64/arch/x86/include/asm/irqflags.h:49
    49              asm volatile("sti; hlt": : :"memory");
    (gdb) c
    Continuing.
    
    Breakpoint 1, sys_getpid () at kernel/timer.c:1344
    1344    {
    (gdb) bt
    #0  sys_getpid () at kernel/timer.c:1344
    #1  0xffffffff810029eb in ?? ()
    #2  0x0000000000000246 in ?? ()
    #3  0x00007fff70d418e0 in ?? ()
    #4  0x00007f6c11b19210 in ?? ()
    #5  0x00007f6c11b05300 in ?? ()
    #6  0x0000000000000027 in ?? ()
    #7  0x0000000000000000 in ?? ()
    (gdb) l
    1339     * which case the tgid is the same in all threads of the same group.
    1340     *
    1341     * This is SMP safe as current->tgid does not change.
    1342     */
    1343    SYSCALL_DEFINE0(getpid)
    1344    {
    1345            return task_tgid_vnr(current);
    1346    }
    1347
    1348    /*
    (gdb) s
    1345            return task_tgid_vnr(current);
    (gdb)
    get_current ()
        at /home/ugrad/07/s0711489/coursework/KernelHack/linux-2.6.35.14/x86_64/arch/x86/include/asm/current.h:14
    14              return percpu_read_stable(current_task);
    (gdb) l
    9
    10      DECLARE_PER_CPU(struct task_struct *, current_task);
    11
    12      static __always_inline struct task_struct *get_current(void)
    13      {
    14              return percpu_read_stable(current_task);
    15      }
    16
    17      #define current get_current()
    18
    (gdb) bt
    #0  get_current ()
        at /home/ugrad/07/s0711489/coursework/KernelHack/linux-2.6.35.14/x86_64/arch/x86/include/asm/current.h:14
    #1  sys_getpid () at kernel/timer.c:1345
    #2  0xffffffff810029eb in ?? ()
    #3  0x0000000000000246 in ?? ()
    #4  0x00007fff63204890 in ?? ()
    #5  0x00007fc615a98210 in ?? ()
    #6  0x00007fc615a84300 in ?? ()
    #7  0x0000000000000027 in ?? ()
    #8  0x0000000000000000 in ?? ()
    (gdb) p current_task
    Cannot access memory at address 0xb540
    (gdb) ptype current_task
    type = struct task_struct {
    
    (snip)
    
    (gdb) s
    sys_getpid () at kernel/timer.c:1344
    1344    {
    (gdb) l
    1339     * which case the tgid is the same in all threads of the same group.
    1340     *
    1341     * This is SMP safe as current->tgid does not change.
    1342     */
    1343    SYSCALL_DEFINE0(getpid)
    1344    {
    1345            return task_tgid_vnr(current);
    1346    }
    1347
    1348    /*
    (gdb) bt
    #0  sys_getpid () at kernel/timer.c:1344
    #1  0xffffffff810029eb in ?? ()
    #2  0x0000000000000246 in ?? ()
    #3  0x00007fff63204890 in ?? ()
    #4  0x00007fc615a98210 in ?? ()
    #5  0x00007fc615a84300 in ?? ()
    #6  0x0000000000000027 in ?? ()
    #7  0x0000000000000000 in ?? ()
    (gdb) s
    1345            return task_tgid_vnr(current);
    (gdb) s
    task_tgid_vnr (tsk=0xffff88001bbe5880) at include/linux/sched.h:1606
    1606    {
    (gdb) l
    1601    }
    1602
    1603    pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
    1604
    1605    static inline pid_t task_tgid_vnr(struct task_struct *tsk)
    1606    {
    1607            return pid_vnr(task_tgid(tsk));
    1608    }
    1609
    1610
    (gdb) bt
    #0  task_tgid_vnr (tsk=0xffff88001bbe5880) at include/linux/sched.h:1606
    #1  0xffffffff81048cf6 in sys_getpid () at kernel/timer.c:1345
    #2  0xffffffff810029eb in ?? ()
    #3  0x0000000000000246 in ?? ()
    #4  0x00007fff63204890 in ?? ()
    #5  0x00007fc615a98210 in ?? ()
    #6  0x00007fc615a84300 in ?? ()
    #7  0x0000000000000027 in ?? ()
    #8  0x0000000000000000 in ?? ()
    (gdb) p tsk
    $2 = (struct task_struct *) 0xffff88001bbe5880
    (gdb) ptype tsk
    type = struct task_struct {
    
    (snip)
    
        pid_t pid;
        pid_t tgid;
    
    (snip)
    
        struct task_struct *group_leader;
        struct list_head ptraced;
        struct list_head ptrace_entry;
        struct pid_link pids[3];
    
    (snip)
    
    (gdb) ptype tsk->group_leader->pids
    type = struct pid_link {
        struct hlist_node node;
        struct pid *pid;
    } [3]
    
    (snip)
    
    (gdb) s
    1607            return pid_vnr(task_tgid(tsk));
    (gdb)
    1606    {
    (gdb)
    1607            return pid_vnr(task_tgid(tsk));
    (gdb)
    pid_vnr (pid=0xffff88001fb55400) at kernel/pid.c:444
    444     {
    (gdb) bt
    #0  pid_vnr (pid=0xffff88001fb55400) at kernel/pid.c:444
    #1  0xffffffff81048783 in task_tgid_vnr (tsk=<value optimized out>)
        at include/linux/sched.h:1607
    #2  0xffffffff81048cf6 in sys_getpid () at kernel/timer.c:1345
    #3  0xffffffff810029eb in ?? ()
    #4  0x0000000000000246 in ?? ()
    #5  0x00007fff63204890 in ?? ()
    #6  0x00007fc615a98210 in ?? ()
    #7  0x00007fc615a84300 in ?? ()
    #8  0x0000000000000027 in ?? ()
    #9  0x0000000000000000 in ?? ()
    (gdb) l
    439             }
    440             return nr;
    441     }
    442
    443     pid_t pid_vnr(struct pid *pid)
    444     {
    445             return pid_nr_ns(pid, current->nsproxy->pid_ns);
    446     }
    447     EXPORT_SYMBOL_GPL(pid_vnr);
    448
    (gdb) ptype pid
    type = struct pid {
        atomic_t count;
        unsigned int level;
        struct hlist_head tasks[3];
        struct rcu_head rcu;
        struct upid numbers[1];
    } *
    (gdb) up
    #1  0xffffffff81048783 in task_tgid_vnr (tsk=<value optimized out>)
        at include/linux/sched.h:1607
    1607            return pid_vnr(task_tgid(tsk));
    (gdb) ptype tsk->nsproxy->pid_ns
    type = struct pid_namespace {
        struct kref kref;
        struct pidmap pidmap[128];
        int last_pid;
        struct task_struct *child_reaper;
        struct kmem_cache *pid_cachep;
        unsigned int level;
        struct pid_namespace *parent;
        struct vfsmount *proc_mnt;
        struct bsd_acct_struct *bacct;
    } *
    (gdb) down
    #0  pid_vnr (pid=0xffff88001fb55400) at kernel/pid.c:444
    444     {
    (gdb) s
    445             return pid_nr_ns(pid, current->nsproxy->pid_ns);
    (gdb)
    get_current (pid=0xffff88001fb55400)
        at /home/ugrad/07/s0711489/coursework/KernelHack/linux-2.6.35.14/x86_64/arch/x86/include/asm/current.h:14
    14              return percpu_read_stable(current_task);
    (gdb) p current_task
    Cannot access memory at address 0xb540
    (gdb) s
    pid_vnr (pid=0xffff88001fb55400) at kernel/pid.c:445
    445             return pid_nr_ns(pid, current->nsproxy->pid_ns);
    (gdb) s
    444     {
    (gdb)
    445             return pid_nr_ns(pid, current->nsproxy->pid_ns);
    (gdb)
    pid_nr_ns (pid=0xffff88001fb55400, ns=0xffffffff8181bfe0) at kernel/pid.c:431
    431     {
    (gdb) bt
    #0  pid_nr_ns (pid=0xffff88001fb55400, ns=0xffffffff8181bfe0)
        at kernel/pid.c:431
    #1  0xffffffff81052db6 in pid_vnr (pid=0xffff88001fb55400) at kernel/pid.c:445
    #2  0xffffffff81048783 in task_tgid_vnr (tsk=<value optimized out>)
        at include/linux/sched.h:1607
    #3  0xffffffff81048cf6 in sys_getpid () at kernel/timer.c:1345
    #4  0xffffffff810029eb in ?? ()
    #5  0x0000000000000246 in ?? ()
    #6  0x00007fff63204890 in ?? ()
    #7  0x00007fc615a98210 in ?? ()
    #8  0x00007fc615a84300 in ?? ()
    #9  0x0000000000000027 in ?? ()
    #10 0x0000000000000000 in ?? ()
    (gdb) l
    426             return pid;
    427     }
    428     EXPORT_SYMBOL_GPL(find_get_pid);
    429
    430     pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
    431     {
    432             struct upid *upid;
    433             pid_t nr = 0;
    434
    435             if (pid && ns->level <= pid->level) {
    (gdb) l
    436                     upid = &pid->numbers[ns->level];
    437                     if (upid->ns == ns)
    438                             nr = upid->nr;
    439             }
    440             return nr;
    441     }
    442
    443     pid_t pid_vnr(struct pid *pid)
    444     {
    445             return pid_nr_ns(pid, current->nsproxy->pid_ns);
    (gdb) ptype pid
    type = struct pid {
        atomic_t count;
        unsigned int level;
        struct hlist_head tasks[3];
        struct rcu_head rcu;
        struct upid numbers[1];
    } *
    (gdb) ptype ns
    type = struct pid_namespace {
        struct kref kref;
        struct pidmap pidmap[128];
        int last_pid;
        struct task_struct *child_reaper;
        struct kmem_cache *pid_cachep;
        unsigned int level;
        struct pid_namespace *parent;
        struct vfsmount *proc_mnt;
        struct bsd_acct_struct *bacct;
    } *
    type = struct upid {
        int nr;
        struct pid_namespace *ns;
        struct hlist_node pid_chain;
    } *
    (gdb) ptype pid_t
    type = int
    (gdb) p ns->level
    $5 = 0
    (gdb) p pid->level
    $6 = 0
    (gdb) p ns->level <= pid->level
    $7 = 1
    (gdb) p ns
    $8 = (struct pid_namespace *) 0xffffffff8181bfe0
    (gdb) p &pid->numbers[ns->level]
    $9 = (struct upid *) 0xffff88001fb55430
    (gdb) p (&pid->numbers[ns->level])->ns
    $10 = (struct pid_namespace *) 0xffffffff8181bfe0
    (gdb) info locals
    upid = <value optimized out>
    nr = <value optimized out>
    (gdb) p nr
    $11 = <value optimized out>
    (gdb) p (&pid->numbers[ns->level])->nr
    $12 = 2225
    (gdb) s
    435             if (pid && ns->level <= pid->level) {
    (gdb)
    431     {
    (gdb)
    435             if (pid && ns->level <= pid->level) {
    (gdb)
    436                     upid = &pid->numbers[ns->level];
    (gdb)
    437                     if (upid->ns == ns)
    (gdb) p upid
    $13 = (struct upid *) 0xffff88001fb55430
    (gdb) s
    438                             nr = upid->nr;
    (gdb) p upid->ns == ns
    $14 = 1
    (gdb) p nr
    $15 = <value optimized out>
    (gdb) p upid->nr
    $16 = 2225
    (gdb) s
    441     }
    (gdb)
    pid_vnr (pid=<value optimized out>) at kernel/pid.c:446
    446     }
    (gdb) s
    task_tgid_vnr (tsk=<value optimized out>) at include/linux/sched.h:1608
    1608    }
    (gdb)
    sys_getpid () at kernel/timer.c:1346
    1346    }
    (gdb)
    sys_getpid () at kernel/timer.c:1345
    1345            return task_tgid_vnr(current);
    (gdb)
    sys_getpid () at kernel/timer.c:1346
    1346    }
    (gdb)
    
  • on VM guest
    • s0711489@ubuntu-lucid64:~/coursework/KernelHack/02$ ./getpid
      getpid() -> 2225
      

location of functions on source file

  • windell57:x86_64 s0711489$ grep percpu_read_stable -r .
    (snip)
    
    ./arch/x86/include/asm/percpu.h:#define percpu_read_stable(var)         percpu_from_op("mov", var, "p" (&(var)))
    
    (snip)
    
  • windell57:x86_64 s0711489$ grep task_tgid -r .
    (snip)
    
    ./include/linux/sched.h:static inline struct pid *task_tgid(struct task_struct *task)
    
    (snip)
    
  • include/linux/sched.h
    static inline struct pid *task_tgid(struct task_struct *task)
    {
    	return task->group_leader->pids[PIDTYPE_PID].pid;
    }
    

get_current function

  • windell57:02 s0711489$ gcc -E ../linux-2.6.35.14/x86_64/arch/x86/include/asm/current.h -I ~/coursework/KernelHack/linux-2.6.35.14/x86_64/include -I ~/coursework/KernelHack/linux-2.6.35.14/x86_64/arch/x86/include/ > current.h
    In file included from /home/ugrad/07/s0711489/coursework/KernelHack/linux-2.6.35.14/x86_64/arch/x86/include/asm/percpu.h:44,
                     from ../linux-2.6.35.14/x86_64/arch/x86/include/asm/current.h:5:
    /home/ugrad/07/s0711489/coursework/KernelHack/linux-2.6.35.14/x86_64/include/linux/kernel.h:733:2: warning: #warning Attempt to use kernel headers from user space, see http:
    
  • pre-processed arch/x86/include/asm/current.h
    static __always_inline struct task_struct *get_current(void)
    {
     return ({ typeof(current_task) pfo_ret__; switch (sizeof(current_task)) { case 1: asm("mov" "b ""%P" "1"",%0" : "=q" (pfo_ret__) : "p" (&(current_task))); break; case 2: asm("mov" "w ""%P" "1"",%0" : "=r" (pfo_ret__) : "p" (&(current_task))); break; case 4: asm("mov" "l ""%P" "1"",%0" : "=r" (pfo_ret__) : "p" (&(current_task))); break; case 8: asm("mov" "q ""%P" "1"",%0" : "=r" (pfo_ret__) : "p" (&(current_task))); break; default: __bad_percpu_size(); } pfo_ret__; });
    }
    

10/12

tee system call

  • http://linuxjm.sourceforge.jp/html/LDP_man-pages/man2/tee.2.html
    #define _GNU_SOURCE
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <limits.h>
    
    int
    main(int argc, char *argv[])
    {
        int fd;
        int len, slen;
    
        if (argc != 2) {
            fprintf(stderr, "Usage: %s <file>\n", argv[0]);
            exit(EXIT_FAILURE);
        }
    
        fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644);
        if (fd == -1) {
            perror("open");
            exit(EXIT_FAILURE);
        }
    
        do {
            /*
             * tee stdin to stdout.
             */
            len = tee(STDIN_FILENO, STDOUT_FILENO,
                      INT_MAX, SPLICE_F_NONBLOCK);
    
            if (len < 0) {
                if (errno == EAGAIN)
                    continue;
                perror("tee");
                exit(EXIT_FAILURE);
            } else
                if (len == 0)
                    break;
    
            /*
             * Consume stdin by splicing it to a file.
             */
            while (len > 0) {
                slen = splice(STDIN_FILENO, NULL, fd, NULL,
                              len, SPLICE_F_MOVE);
                if (slen < 0) {
                    perror("splice");
                    break;
                }
                len -= slen;
            }
        } while (1);
    
        close(fd);
        exit(EXIT_SUCCESS);
    }
    
  • Ubuntu lucid(2.6.32-33-generic)やvanilla 2.6.35.14ではサンプルコードのまま正常に使える
    • mitty@ubuntu64:~/coursework/KernelHack/02$ cat tee.c | ./tee hoge | wc
           58     130    1217
      
  • CentOS 5.7(2.6.18-238.19.1.el5.centos.plusPAE or 2.6.18-274.3.1.el5)ではspliceがエラーになる
    • viola01:02 s0711489$ cat tee.c | ./tee hoge | wc
      viola01:02 s0711489$ cat tee.c | ./tee hoge | wc
      splice: Invalid argument
      splice: Invalid argument
      splice: Invalid argument
      splice: Invalid argument
      splice: Invalid argument
      splice: Invalid argument
      splice: Invalid argument
      splice: Invalid argument
      splice: Invalid argument
      
      ....
      
  • Ubuntu上でも、strace出来ない
    • mitty@ubuntu64:~/coursework/KernelHack/02$ strace -f -o sh.log sh -c 'cat tee.c | ./tee hoge | wc'
    • mitty@ubuntu64:~/coursework/KernelHack/02$ less sh.log
      (snip)
      
      1611  <... tee resumed> )               = -1 EAGAIN (Resource temporarily unavailable)
      1611  tee(0, 0x1, 0x7fffffff, 0x2)      = -1 EAGAIN (Resource temporarily unavailable)
      1611  tee(0, 0x1, 0x7fffffff, 0x2)      = -1 EAGAIN (Resource temporarily unavailable)
      1611  tee(0, 0x1, 0x7fffffff, 0x2)      = -1 EAGAIN (Resource temporarily unavailable)
      1611  tee(0, 0x1, 0x7fffffff, 0x2)      = -1 EAGAIN (Resource temporarily unavailable)
      1611  tee(0, 0x1, 0x7fffffff, 0x2)      = -1 EAGAIN (Resource temporarily unavailable)
      1611  tee(0, 0x1, 0x7fffffff, 0x2)      = -1 EAGAIN (Resource temporarily unavailable)
      
      (snip)
      
  • GDBによるステップ実行は、3000行ほど実行してみたがguest側で結果が出力されないので、断念

Attachments (1)

Download all attachments as: .zip