Chinaunix

标题: 向高手请教AT&T汇编语法,谢谢 [打印本页]

作者: qiangtoucao121    时间: 2007-09-28 17:47
标题: 向高手请教AT&T汇编语法,谢谢
0xffffffff8013091a <__wake_up_common+58>:       mov    0xffffffffffffffd0(%rbp),%edx
0xffffffff8013091d <__wake_up_common+61>:       mov    0xffffffffffffffd4(%rbp),%esi
0xffffffff80130920 <__wake_up_common+64>:       callq  *0xfffffffffffffff8(%rax)
用gdb反编译得到上述指令,请教高人能否解释一下0xffffffffffffffd0是什么意思。
callq  *0xfffffffffffffff8(%rax)这条指令是什么意思?
作者: mik    时间: 2007-09-28 21:39
>> mov    0xffffffffffffffd0(%rbp),%edx
     等于: mov eax, [rbp -  48 ]


>> callq  *0xfffffffffffffff8(%rax)
     等于: call qword ptr [rax - 8 ]
作者: qiangtoucao121    时间: 2007-09-29 09:04
老大可不可以介绍一本64位汇编入门的书,或者网站什么的,英文的也可以,谢谢!
作者: qiangtoucao121    时间: 2007-09-29 09:07
(gdb) file vmlinux
Reading symbols from /usr/src/linux-2.6.11.4-21.7/vmlinux...(no debugging symbols found)...done.
(gdb) disassemble __wake_up_common
Dump of assembler code for function __wake_up_common:
0xffffffff801308e0 <__wake_up_common+0>:        push   %rbp
0xffffffff801308e1 <__wake_up_common+1>:        mov    %rsp,%rbp
0xffffffff801308e4 <__wake_up_common+4>:        push   %r15
0xffffffff801308e6 <__wake_up_common+6>:        mov    %r8,%r15
0xffffffff801308e9 <__wake_up_common+9>:        push   %r14
0xffffffff801308eb <__wake_up_common+11>:       lea    0x8(%rdi),%r14
0xffffffff801308ef <__wake_up_common+15>:       push   %r13
0xffffffff801308f1 <__wake_up_common+17>:       mov    %edx,%r13d
0xffffffff801308f4 <__wake_up_common+20>:       push   %r12
0xffffffff801308f6 <__wake_up_common+22>:       push   %rbx
0xffffffff801308f7 <__wake_up_common+23>:       sub    $0x8,%rsp
0xffffffff801308fb <__wake_up_common+27>:       mov    %esi,0xffffffffffffffd4(%rbp)
0xffffffff801308fe <__wake_up_common+30>:       mov    %ecx,0xffffffffffffffd0(%rbp)
0xffffffff80130901 <__wake_up_common+33>:       mov    0x8(%rdi),%rax
0xffffffff80130905 <__wake_up_common+37>:       cmp    %r14,%rax
0xffffffff80130908 <__wake_up_common+40>:       mov    (%rax),%r12
0xffffffff8013090b <__wake_up_common+43>:       je     0xffffffff8013093e <__wake_up_common+94>
0xffffffff8013090d <__wake_up_common+45>:       data16
0xffffffff8013090e <__wake_up_common+46>:       data16
0xffffffff8013090f <__wake_up_common+47>:       nop   
0xffffffff80130910 <__wake_up_common+48>:       lea    0xffffffffffffffe8(%rax),%rdi
0xffffffff80130914 <__wake_up_common+52>:       mov    0xffffffffffffffe8(%rax),%ebx
0xffffffff80130917 <__wake_up_common+55>:       mov    %r15,%rcx
0xffffffff8013091a <__wake_up_common+58>:       mov    0xffffffffffffffd0(%rbp),%edx
0xffffffff8013091d <__wake_up_common+61>:       mov    0xffffffffffffffd4(%rbp),%esi
0xffffffff80130920 <__wake_up_common+64>:       callq  *0xfffffffffffffff8(%rax)
0xffffffff80130923 <__wake_up_common+67>:       test   %eax,%eax
0xffffffff80130925 <__wake_up_common+69>:       je     0xffffffff80130932 <__wake_up_common+82>
0xffffffff80130927 <__wake_up_common+71>:       and    $0x1,%ebx
0xffffffff8013092a <__wake_up_common+74>:       je     0xffffffff80130932 <__wake_up_common+82>
作者: qiangtoucao121    时间: 2007-09-29 09:08
0xffffffff8013092c <__wake_up_common+76>:       dec    %r13d
0xffffffff8013092f <__wake_up_common+79>:       nop   
0xffffffff80130930 <__wake_up_common+80>:       je     0xffffffff8013093e <__wake_up_common+94>
0xffffffff80130932 <__wake_up_common+82>:       mov    %r12,%rax
0xffffffff80130935 <__wake_up_common+85>:       mov    (%r12),%r12
0xffffffff80130939 <__wake_up_common+89>:       cmp    %r14,%rax
0xffffffff8013093c <__wake_up_common+92>:       jne    0xffffffff80130910 <__wake_up_common+48>
0xffffffff8013093e <__wake_up_common+94>:       add    $0x8,%rsp
0xffffffff80130942 <__wake_up_common+98>:       pop    %rbx
0xffffffff80130943 <__wake_up_common+99>:       pop    %r12
0xffffffff80130945 <__wake_up_common+101>:      pop    %r13
0xffffffff80130947 <__wake_up_common+103>:      pop    %r14
0xffffffff80130949 <__wake_up_common+105>:      pop    %r15
0xffffffff8013094b <__wake_up_common+107>:      leaveq
0xffffffff8013094c <__wake_up_common+108>:      retq   
0xffffffff8013094d <__wake_up_common+109>:      data16
0xffffffff8013094e <__wake_up_common+110>:      data16
0xffffffff8013094f <__wake_up_common+111>:      nop
作者: qiangtoucao121    时间: 2007-09-29 09:09
死机前源码:
/*
* The core wakeup function.  Non-exclusive wakeups (nr_exclusive == 0) just
* wake everything up.  If it's an exclusive wakeup (nr_exclusive == small +ve
* number) then we wake all the non-exclusive tasks and one exclusive task.
*
* There are circumstances in which we can try to wake a task which has already
* started to run but is not in state TASK_RUNNING.  try_to_wake_up() returns
* zero in this (rare) case, and we handle it by continuing to scan the queue.
*/
static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
                             int nr_exclusive, int sync, void *key)
{
        struct list_head *tmp, *next;

        list_for_each_safe(tmp, next, &q->task_list) {
                wait_queue_t *curr;
                unsigned flags;
                curr = list_entry(tmp, wait_queue_t, task_list);
                flags = curr->flags;
                if (curr->func(curr, mode, sync, key) &&
                    (flags & WQ_FLAG_EXCLUSIVE) &&
                    !--nr_exclusive)
                        break;
        }
}

/**
* __wake_up - wake up threads blocked on a waitqueue.
* @q: the waitqueue
* @mode: which threads
* @nr_exclusive: how many wake-one or wake-many threads to wake up
*/
void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode,
                                int nr_exclusive, void *key)
{
        unsigned long flags;

        spin_lock_irqsave(&q->lock, flags);
        __wake_up_common(q, mode, nr_exclusive, 0, key);
        spin_unlock_irqrestore(&q->lock, flags);
}
作者: qiangtoucao121    时间: 2007-09-29 09:10
HBDS-IPSAN:~ # Unable to handle kernel NULL pointer dereference at 0000000000000000 RIP:

[<0000000000000000>]

PGD 338bf067 PUD 78013067 PMD 0

Oops: 0010 [1] SMP
CPU 1
Modules linked in: evdev st sr_mod nfsd kvbdi sg fsiscsi kdbackup kipstor kfsnalias kfsnevt krudp kfsnbase fsnlzo edd thermal processor fan button battery ac i2c_dev ipv6 basp i2c_i801 i2c_core bccfg video1394 ohci1394 raw1394 ieee1394 capability dm_mod ext3 jbd xfs exportfs ide_cd cdrom ide_disk tg3 e100 mii bcraid piix ide_core sd_mod scsi_mod
Pid: 19025, comm: ps Tainted: PF    U 2.6.11.4-21.7-smp
RIP: 0010:[<0000000000000000>] [<0000000000000000>]
RSP: 0018:ffff81007f95fcb0  EFLAGS: 00010097
RAX: ffff81003322db90 RBX: 00000000000005a8 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff81003322db78
RBP: ffff81007f95fce8 R08: 000000000000000a R09: 0000000000019a28
R10: 0000000000019a28 R11: ffff81007cb78040 R12: ffff810032d4c130
R13: 0000000000000001 R14: ffff810079f085b8 R15: 0000000000000000
FS:  00002aaaaade8b00(0000) GS:ffffffff804e3980(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000000 CR3: 0000000033c34000 CR4: 00000000000006e0
Process ps (pid: 19025, threadinfo ffff810033772000, task ffff810032cc9890)
Stack: ffffffff80130a23 0000000100000000 ffff810079f085b0 0000000000000000
       0000000000000001 0000000000000296 0000000000000001 ffff81007f95fd28
       ffffffff801322a3 0000000000000001
Call Trace:<IRQ> <ffffffff80130a23>{__wake_up_common+67} <ffffffff801322a3>{__wake_up+67}
       <ffffffff802f851f>{tcp_v4_rcv+1727} <ffffffff88063aef>{:bcraid:_Z14RC_STH_SendRawv+607}
       <ffffffff802ddca1>{ip_local_deliver+385} <ffffffff802dd833>{ip_rcv+1075}
       <ffffffff801413e5>{__mod_timer+309} <ffffffff802c0420>{netif_receive_skb+944}
       <ffffffff88160f4d>{:tg3:tg3_poll+2077} <ffffffff802bf054>{net_rx_action+132}
       <ffffffff8013cbb1>{__do_softirq+113} <ffffffff8013cc65>{do_softirq+53}
       <ffffffff80111767>{do_IRQ+71} <ffffffff8010efa7>{ret_from_intr+0}
        <EOI> <ffffffff80226dee>{_atomic_dec_and_lock+30}
       <ffffffff80197691>{dput+33} <ffffffff8018ee3b>{link_path_walk+3515}
       <ffffffff8018f
作者: qiangtoucao121    时间: 2007-09-29 09:18
以上分别给出了OOP消息,__wake_up_common的源代码和反编译的源代码,请问根据这些信息是否可以确定是哪里出了问题?怎么分析?
从调用栈的的情况的话,应该是__wake_up_common+67出了问题
根据反编译和_wake_up_common代码的信息,可以确定是
if (curr->func(curr, mode, sync, key) &&
                    (flags & WQ_FLAG_EXCLUSIVE) &&
                    !--nr_exclusive)
出了问题,因为整个__wake_up_common只有一个函数调用,而list_for_each_safe()和list_entry均是宏定义,接下来该如何分析,是不是可以确定func没有被初始化而造成的?(func是一个函数指针),下面是wait_queue_t的数据结构:
typedef struct __wait_queue wait_queue_t;
typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int sync, void *key);
int default_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
struct __wait_queue {
        unsigned int flags;
#define WQ_FLAG_EXCLUSIVE        0x01
        struct task_struct * task;
        wait_queue_func_t func;
        struct list_head task_list;
};
作者: qiangtoucao121    时间: 2007-09-29 15:59
我的e-mail: flybird525#h3c.com,请发给我你那本<<gnu assembly>>
谢谢了!
作者: mik    时间: 2007-09-29 21:45
可惜对 linux kernel 不熟。
从 OOPS 提供的信息来看。
1、死机发生的原因是:Unable to handle kernel NULL pointer dereference at 0000000000000000 RIP
也就是kernel发生了尝试读取0地址指令,从而导致#GP异常而被终止

2、根据以上判断,发生错误的指令只可能是这条:
0xffffffff80130920 <__wake_up_common+64>:       callq  *0xfffffffffffffff8(%rax)
也就是 [rax - 8] 这个内存中被写入 0,从而导致 call 指令调用时,rip 被装入 0

3、是什么情况下 [rax - 8] 被写入0了? 要进行调试跟踪才能发现了
作者: qiangtoucao121    时间: 2007-09-30 09:43
老大,能给我简单的讲讲调试跟踪内核的方法吗?谢谢!
作者: mik    时间: 2007-10-01 17:56
原帖由 qiangtoucao121 于 2007-9-30 09:43 发表
老大,能给我简单的讲讲调试跟踪内核的方法吗?谢谢!


惭愧,偶不是 linux kernel 爱好者,没学习过 linux kernel,所以不了解 kernel 调试方法

不过,偶喜欢分析汇编代码:
  1.      push   %rbp
  2.         mov    %rsp,%rbp
  3.         push   %r15
  4.         mov    %r8,%r15                                   /* key */
  5.         push   %r14
  6.        lea    0x8(%rdi),%r14                           /* r14 = &q->task_list */
  7.        push   %r13
  8.        mov    %edx,%r13d                             /* r13d = nr_exclusive */
  9.        push   %r12
  10.        push   %rbx
  11.        sub    $0x8,%rsp           
  12.        mov    %esi,0xffffffffffffffd4(%rbp)      /* [rbp-40] = mode */
  13.        mov    %ecx,0xffffffffffffffd0(%rbp)      /* [rbp-48] = sync */
  14.        mov    0x8(%rdi),%rax                      /* rax = q->task_list */
  15.        cmp    %r14,%rax                            /* 判断是否回到头节点 */
  16.        mov    (%rax),%r12                        /* r12 = *q->task_list */
  17.        je     0xffffffff8013093e <__wake_up_common+94>
  18.        data16
  19.        data16
  20.        nop   
  21.        lea    0xffffffffffffffe8(%rax),%rdi                /* curr */
  22.        mov    0xffffffffffffffe8(%rax),%ebx   
  23.        mov    %r15,%rcx                                    /* key */
  24.        mov    0xffffffffffffffd0(%rbp),%edx          /* sync */
  25.        mov    0xffffffffffffffd4(%rbp),%esi            /* mode */
  26.        callq  *0xfffffffffffffff8(%rax)                     /* curr->func() */
  27.        test   %eax,%eax
  28.        je     0xffffffff80130932 <__wake_up_common+82>
  29.        and    $0x1,%ebx
  30.        je     0xffffffff80130932 <__wake_up_common+82>
  31.        dec    %r13d
  32.        nop   
  33.        je     0xffffffff8013093e <__wake_up_common+94>
  34.        mov    %r12,%rax                               /* rax = *q->task_list */
  35.        mov    (%r12),%r12                           / q->task_list = *q->task_list */
  36.        cmp    %r14,%rax                             /* 判断是否回到头节点 */
  37.        jne    0xffffffff80130910 <__wake_up_common+48>
  38.        add    $0x8,%rsp
  39.        pop    %rbx
  40.        pop    %r12
  41.       pop    %r13
  42.       pop    %r14
  43.       pop    %r15
  44.       leaveq
  45.       retq   
  46.       data16
  47.       data16
  48.       nop
复制代码

curr->func 被置为 0 时,就出现了以下的错误。

偶给你介绍一下 AMD64 的 ABI 几个特性:
1、7个通用寄存器(rdi,rsi,rdx,rcx,r8,r9 和 rax)依次用作函数传递参数。
2、rsp 及 rbp 用于管理堆栈
3、r10 及 r11 用于临时寄存器
4、5个通用寄存器(r12,r13,r14,r15 及 rbx)由被调用方保存




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2