一种“特殊”的调试手段

1 篇文章 0 订阅
在考文档:http://yuanma.org/data/2008/0610/article_3064.htm

原文的目的是用来解决Oops时没有相应的vmlinux在手的办法。传说是Linus的喜好。我尝试把它扩展到其他程序中。
在Oops中会看到:
Code: 6b c0 e8 2e 7e f6 ff e8 d1 16 f2 ff b8 01 00 00 00 e8 aa 1c f4 ff 89 d8 83 c4 10 5b 5d c3 90 90 90 55 89 e5 53 83 ec 0c 8b 48 04 <8b> 11 39 c2 74 18 89 54 24 08 89 44 24 04 c7 04 24 be 32 6b c0  

这东东有点作用,只要你写:

                const char array[] = "/xnn/xnn/xnn...";
                int main(int argc, char *argv[])
                {
                        printf("%p/n", array);
                        *(int *)0 = 0;
                }


其中const char array[]的值用上面的那堆code代替即可。然后gcc -g -o 编译出程序,用gdb执行:
(gdb) r
                Starting program: /home/arc/hello
                0x80484e0

                Program received signal SIGSEGV, Segmentation fault.


然后反编译:
(gdb) disassemble 0x80484e0
                Dump of assembler code for function array:
                0x080484e0 <array+0>:   imul   $0xffffffe8,%eax,%eax
                0x080484e3 <array+3>:   jle,pn 0x80484dc <__dso_handle+20>
                0x080484e6 <array+6>:   ljmp   *<internal disassembler error>
                0x080484e8 <array+8>:   rcll   (%esi)
                0x080484ea <array+10>:  repnz (bad)
                0x080484ec <array+12>:  mov    $0x1,%eax
                0x080484f1 <array+17>:  call   0x7f8a1a0
                0x080484f6 <array+22>:  mov    %ebx,%eax
                0x080484f8 <array+24>:  add    $0x10,%esp
                0x080484fb <array+27>:  pop    %ebx
                0x080484fc <array+28>:  pop    %ebp
                0x080484fd <array+29>:  ret
                0x080484fe <array+30>:  nop
                0x080484ff <array+31>:  nop
                0x08048500 <array+32>:  nop
                0x08048501 <array+33>:  push   %ebp
                0x08048502 <array+34>:  mov    %esp,%ebp
                0x08048504 <array+36>:  push   %ebx
                0x08048505 <array+37>:  sub    $0xc,%esp
                0x08048508 <array+40>:  mov    0x4(%eax),%ecx
                0x0804850b <array+43>:  mov    (%ecx),%edx
                0x0804850d <array+45>:  cmp    %eax,%edx
                0x0804850f <array+47>:  je     0x8048529
                0x08048511 <array+49>:  mov    %edx,0x8(%esp)
                0x08048515 <array+53>:  mov    %eax,0x4(%esp)
                0x08048519 <array+57>:  movl   $0xc06b32be,(%esp)
                0x08048520 <array+64>:  add    %ah,0xa70
                End of assembler dump.

这样就可以看到<8b>的位置,即array[43]对应的是move (%ecx), %edx,根据AT&T汇编程序的写法,可以知道问题出现在%ecx指向的地址有问题。

然后我把这个问题应用到jni的crash中去。

首先看crash log的开头,这里已经有很重要的信息:

#
# An unexpected error has been detected by Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x6fd1dba5, pid=29450, tid=3086605200
#
# Java VM: Java HotSpot(TM) Server VM (1.6.0_03-b05 mixed mode)
# Problematic frame:
# C  [libdb_java-4.2.so+0x15ba5]  Java_com_sleepycat_db_db_1javaJNI_initDbEnvRef0+0x25
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp

注意pc值。

找到code:
Instructions: (pc=0x6fd1dba5)
0x6fd1db95:   8b 45 18 89 75 f0 89 0c 24 89 44 24 04 ff 52 54
0x6fd1dba5:   89 86 e8 00 00 00 89 74 24 04 89 34 24 ff 96 50

注意寄存器数据:
Registers:
EAX=0x707db9d8, EBX=0x71122a80, ECX=0x00000000, EDX=0x00000ffc
ESP=0xb7f9ce30, EBP=0xb7f9ce48, ESI=0x00000000, EDI=0x091a3800
EIP=0x6fd1dba5, CR2=0x000000e8, EFLAGS=0x00010246

查看callstack:
Stack: [0xb7f4d000,0xb7f9e000),  sp=0xb7f9ce30,  free space=319k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libdb_java-4.2.so+0x15ba5]  Java_com_sleepycat_db_db_1javaJNI_initDbEnvRef0+0x25
j  com.sleepycat.db.db_javaJNI.initDbEnvRef0(JLjava/lang/Object;)Ljava/lang/Object;+0
j  com.sleepycat.db.db_java.initDbEnvRef0(Lcom/sleepycat/db/DbEnv;Ljava/lang/Object;)Ljava/lang/Object;+5
j  com.sleepycat.db.DbEnv.initialize()V+3
j  com.sleepycat.db.DbEnv.<init>(I)V+10

然后写个小程序,把code输入,然后反汇编:
(gdb) disassemble 0x8048500
Dump of assembler code for function array:
0x08048500 <array+0>:   mov    0x18(%ebp),%eax
0x08048503 <array+3>:   mov    %esi,0xfffffff0(%ebp)
0x08048506 <array+6>:   mov    %ecx,(%esp)
0x08048509 <array+9>:   mov    %eax,0x4(%esp)
0x0804850d <array+13>:  call   *0x54(%edx)
0x08048510 <array+16>:  mov    %eax,0xe8(%esi)
0x08048516 <array+22>:  mov    %esi,0x4(%esp)
0x0804851a <array+26>:  mov    %esi,(%esp)
0x0804851d <array+29>:  call   *0x70250050(%esi)

出问题的应该是这句:
0x08048510 <array+16>:  mov    %eax,0xe8(%esi)

根据AT&T汇编的特点,应该是%esi + 0xe8这个位置非法。现在%esi的值为0,不用想都知道这个位置非法了。
然后查看源代码:

找到
com.sleepycat.db.db_javaJNI.initDbEnvRef0(JLjava/lang/Object;)Ljava/lang/Object;+0

JNIEXPORT jobject JNICALL Java_com_sleepycat_db_db_1javaJNI_initDbEnvRef0(
    JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg2) {
    DB_ENV *self = *(DB_ENV **)&jarg1;
    COMPQUIET(jcls, NULL);

    DB_ENV_INTERNAL(self) = (void *)(*jenv)->NewGlobalRef(jenv, jarg2);       --> (1)
    self->set_errpfx(self, (const char*)self);                                --> (2)
    return (jobject)DB_ENV_INTERNAL(self);
}

问题不在(1)不在(2)了

到此为止前没有解决问题,毕竟我不是专门弄berkeley db的,只好goo一下了,找了个patch,现在正在测试。。。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值