代码改变世界

[Advance] How to debug a program (下):示例

2011-03-23 13:10  zhenjing  阅读(1237)  评论(0编辑  收藏  举报

参考:[Advance] How to debug a program (上)



Example

Test ENV

nochen@bclnx64 ~/test$ uname -a
Linux bclnx64 2.6.9-34.ELsmp #1 SMP Thu Mar 9 06:23:23 GMT 2006 x86_64 x86_64 x86_64 GNU/Linux
nochen@bclnx64 ~/test$ g++ -v
Reading specs from /usr/lib/gcc/x86_64-redhat-linux/3.4.5/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=x86_64-redhat-linux
Thread model: posix
gcc version 3.4.5 20051201 (Red Hat 3.4.5-2)
nochen@bclnx64 ~/test$ gdb -v
GNU gdb Red Hat Linux (6.3.0.0-1.96rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
 

Example 1

Aim: basic stack usage, basic assemble code
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

int Add(int a, int b, int c){
    int arr[4] = {0};
    arr[0] = a;
    arr[1] = b;
    arr[2] = c;

    arr[3] = a+b+c;
    return arr[3];
}

int main() {
    int a = 0x100;
    int b = 0x200;
    int c = 0x345;

    Add(a,b,c);
    return 1;
}
  gdb ./test
(gdb) x/40i Add-2
0x400506 <frame_dummy+38>:      nop
0x400507 <frame_dummy+39>:      nop
0x400508 <_Z3Addiii>:   push   %rbp
0x400509 <_Z3Addiii+1>: mov    %rsp,%rbp
0x40050c <_Z3Addiii+4>: mov    %edi,0xfffffffffffffffc(%rbp)
0x40050f <_Z3Addiii+7>: mov    %esi,0xfffffffffffffff8(%rbp)
0x400512 <_Z3Addiii+10>:        mov    %edx,0xfffffffffffffff4(%rbp)
0x400515 <_Z3Addiii+13>:        movq   $0x0,0xffffffffffffffe0(%rbp)
0x40051d <_Z3Addiii+21>:        movq   $0x0,0xffffffffffffffe8(%rbp)
0x400525 <_Z3Addiii+29>:        mov    0xfffffffffffffffc(%rbp),%eax
0x400528 <_Z3Addiii+32>:        mov    %eax,0xffffffffffffffe0(%rbp)
0x40052b <_Z3Addiii+35>:        mov    0xfffffffffffffff8(%rbp),%eax
0x40052e <_Z3Addiii+38>:        mov    %eax,0xffffffffffffffe4(%rbp)
0x400531 <_Z3Addiii+41>:        mov    0xfffffffffffffff4(%rbp),%eax
0x400534 <_Z3Addiii+44>:        mov    %eax,0xffffffffffffffe8(%rbp)
0x400537 <_Z3Addiii+47>:        mov    0xfffffffffffffff8(%rbp),%eax
0x40053a <_Z3Addiii+50>:        add    0xfffffffffffffffc(%rbp),%eax
0x40053d <_Z3Addiii+53>:        add    0xfffffffffffffff4(%rbp),%eax
0x400540 <_Z3Addiii+56>:        mov    %eax,0xffffffffffffffec(%rbp)
0x400543 <_Z3Addiii+59>:        mov    0xffffffffffffffec(%rbp),%eax
0x400546 <_Z3Addiii+62>:        leaveq
0x400547 <_Z3Addiii+63>:        retq
0x400548 <main>:        push   %rbp
0x400549 <main+1>:      mov    %rsp,%rbp
0x40054c <main+4>:      sub    $0x10,%rsp
0x400550 <main+8>:      movl   $0x100,0xfffffffffffffffc(%rbp)
0x400557 <main+15>:     movl   $0x200,0xfffffffffffffff8(%rbp)
0x40055e <main+22>:     movl   $0x345,0xfffffffffffffff4(%rbp)
0x400565 <main+29>:     mov    0xfffffffffffffff4(%rbp),%edx
0x400568 <main+32>:     mov    0xfffffffffffffff8(%rbp),%esi
0x40056b <main+35>:     mov    0xfffffffffffffffc(%rbp),%edi
0x40056e <main+38>:     callq  0x400508 <_Z3Addiii>
0x400573 <main+43>:     mov    $0x1,%eax
0x400578 <main+48>:     leaveq
0x400579 <main+49>:     retq
0x40057a <main+50>:     nop
(gdb) b Add
Breakpoint 1 at 0x400515: file stack2.cc, line 20.
(gdb) r
Starting program: /home/nochen/test/test
Breakpoint 1, Add (a=256, b=512, c=837) at stack2.cc:20
20                        int arr[4] = {0};
(gdb) info register
rax            0x645    1605
rbx            0x0      0
rcx            0x20     32
rdx            0x345    837
rsi            0x200    512
rdi            0x100    256
rbp            0x7fbffff480     0x7fbffff480
rsp            0x7fbffff480     0x7fbffff480
r8             0x7fbffff4d0     548682069200
rip            0x400543 0x400543 <Add(int, int, int)+59>
eflags         0x302    770
(gdb) x/60gx $sp-32
0x7fbffff460:   0x0000020000000100      0x0000064500000345
0x7fbffff470:   0x00000345f5614c40      0x0000010000000200 // Add()ocal variables
0x7fbffff480:   0x0000007fbffff4a0      0x0000000000400573 //current rbp - last rbp - ret add
0x7fbffff490:   0x0000034500000000      0x0000010000000200 //main()ocal variables
0x7fbffff4a0:   0x0000003cf5b31738      0x0000003cf591c4bb //main rbp
0x7fbffff4b0:   0x0000000000400450      0x0000007fbffff578
0x7fbffff4c0:   0x0000000100000000      0x0000000000400548
 

Example 2

Aim: basic stack usage, basic assemble code
 
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
 
int Add(int a, int b, int c){
    return a+b+c;
}
 
int main() {
    int a = 0x100;
    int b = 0x200;
    int c = 0x345;
 
    Add(a,b,c);
    return 1;
}
 
gdb ./test
(gdb) x/40i Add
0x400508 <_Z3Addiii>:   push   %rbp
0x400509 <_Z3Addiii+1>: mov    %rsp,%rbp
0x40050c <_Z3Addiii+4>: mov    %edi,0xfffffffffffffffc(%rbp)
0x40050f <_Z3Addiii+7>: mov    %esi,0xfffffffffffffff8(%rbp)
0x400512 <_Z3Addiii+10>:        mov    %edx,0xfffffffffffffff4(%rbp)
0x400515 <_Z3Addiii+13>:        mov    0xfffffffffffffff8(%rbp),%eax
0x400518 <_Z3Addiii+16>:        add    0xfffffffffffffffc(%rbp),%eax
0x40051b <_Z3Addiii+19>:        add    0xfffffffffffffff4(%rbp),%eax
0x40051e <_Z3Addiii+22>:        leaveq
0x40051f <_Z3Addiii+23>:        retq
0x400520 <main>:        push   %rbp
0x400521 <main+1>:      mov    %rsp,%rbp
0x400524 <main+4>:      sub    $0x10,%rsp
0x400528 <main+8>:      movl   $0x100,0xfffffffffffffffc(%rbp)
0x40052f <main+15>:     movl   $0x200,0xfffffffffffffff8(%rbp)
0x400536 <main+22>:     movl   $0x345,0xfffffffffffffff4(%rbp)
0x40053d <main+29>:     mov    0xfffffffffffffff4(%rbp),%edx
0x400540 <main+32>:     mov    0xfffffffffffffff8(%rbp),%esi
0x400543 <main+35>:     mov    0xfffffffffffffffc(%rbp),%edi
0x400546 <main+38>:     callq  0x400508 <_Z3Addiii>
0x40054b <main+43>:     mov    $0x1,%eax
0x400550 <main+48>:     leaveq
0x400551 <main+49>:     retq
0x400552 <main+50>:     nop
(gdb) b Add
Breakpoint 1 at 0x400515: file stack2.cc, line 29.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/nochen/test/test
 
Breakpoint 1, Add (a=256, b=512, c=837) at stack2.cc:29
29          return a+b+c;
(gdb) info register
rax            0x0      0
rbx            0x0      0
rcx            0x20     32
rdx            0x345    837
rsi            0x200    512
rdi            0x100    256
rbp            0x7fbffff480     0x7fbffff480
rsp            0x7fbffff480     0x7fbffff480
r8             0x7fbffff4d0     548682069200
rip            0x400515 0x400515 <Add(int, int, int)+13>
eflags         0x206    518
 (gdb) s
30      }
(gdb) x/16gx 0x7fbffff480-32
0x7fbffff460:   0x0000003cf87dfb00      0x0000000000000000
0x7fbffff470:   0x00000345f5614c40      0x0000010000000200
0x7fbffff480:   0x0000007fbffff4a0      0x000000000040054b
0x7fbffff490:   0x0000034500000000      0x0000010000000200
0x7fbffff4a0:   0x0000003cf5b31738      0x0000003cf591c4bb
0x7fbffff4b0:   0x0000000000400450      0x0000007fbffff578
0x7fbffff4c0:   0x0000000100000000      0x0000000000400520
0x7fbffff4d0:   0x0000000000000000      0x0000003cf5614c40

Example 3

Aim: a case for crashing stack

#include <stdlib.h>

 

int main (int argc, char** argv ) {

  execve("/bin/sh", NULL, NULL); // correct: execve("/bin/sh", argv, NULL);

}

 
gdb ./test
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400570 <main+0>:    push   %rbp
0x0000000000400571 <main+1>:    mov    %rsp,%rbp
0x0000000000400574 <main+4>:    sub    $0x10,%rsp
0x0000000000400578 <main+8>:    mov    %edi,0xfffffffffffffffc(%rbp)
0x000000000040057b <main+11>:   mov    %rsi,0xfffffffffffffff0(%rbp)
0x000000000040057f <main+15>:   mov    $0x0,%edx
0x0000000000400584 <main+20>:   mov    $0x0,%esi
0x0000000000400589 <main+25>:   mov    $0x40068c,%edi
0x000000000040058e <main+30>:   callq  0x400480 // Use ‘disassemble execve’to get execve code  // a little different with: 0x400480
0x0000000000400593 <main+35>:   mov    $0x1,%eax
0x0000000000400598 <main+40>:   leaveq
0x0000000000400599 <main+41>:   retq
End of assembler dump.
(gdb) r
Starting program: /home/nochen/test/test
 
Program received signal SIGSEGV, Segmentation fault.
0x0000000000418969 in ?? ()
(gdb) bt
#0  0x0000000000418969 in ?? ()
#1  0x0000000000000000 in ?? ()
(gdb) info register
rax            0x0      0
rbx            0x0      0
rcx            0x3cf592e813     261818083347
rdx            0x0      0
rsi            0x0      0
rdi            0x0      0
rbp            0x5b4870 0x5b4870  // rbp is wrong. I think Stack crash
rsp            0x7fbffffbb0     0x7fbffffbb0
rip            0x418969 0x418969
eflags         0x10246  66118
 (gdb) x/16gx 0x5b4870-16
0x5b4860:       0x0000003cf5b2e680      0x0000000000000000
0x5b4870:       0x0000007fbffffee0      0x0000003cf5b2eb00
0x5b4880:       0x0000000000000000      0x0000000000000000
0x5b4890:       0x0000003cf5b2e8c0      0x0000000000000000
0x5b48a0:       0x0000000000000000      0x0000000000000000
0x5b48b0:       0x0000000000000000      0x0000000000000000
0x5b48c0:       0x0000000000000000      0x0000000000000000
0x5b48d0:       0x0000000000000000      0x0000000000000000
(gdb) x/16gx 0x0000007fbffffee0-16
0x7fbffffed0:   0x0000000000000000      0x0000000000000000
0x7fbffffee0:   0x0000000000000000      0x0000000000000010 // wrong last rbp addr
0x7fbffffef0:   0x00000000bfebfbff      0x0000000000000006
0x7fbfffff00:   0x0000000000001000      0x0000000000000011
0x7fbfffff10:   0x0000000000000064      0x0000000000000003
0x7fbfffff20:   0x0000000000400040      0x0000000000000004
0x7fbfffff30:   0x0000000000000038      0x0000000000000005
0x7fbfffff40:   0x0000000000000009      0x0000000000000007
(gdb) x/16i 0x0000000000418969-8
0x418961:       add    %cl,0xffffffffffffff89(%rax)
0x418964:       add    $0x19bf4f,%eax
0x418969:       cmpb   $0x2d,(%rax)
0x41896c:       je     0x418c46
0x418972:       mov    1687359(%rip),%rdx        # 0x5b48b8
0x418979:       cmpb   $0x73,(%rdx)
0x41897c:       je     0x418c21
0x418982:       mov    1687343(%rip),%rdx        # 0x5b48b8
0x418989:       cmpb   $0x73,(%rdx)
0x41898c:       je     0x418bfa
0x418992:       mov    1705607(%rip),%rdi        # 0x5b9020
0x418999:       mov    %rbx,1687320(%rip)        # 0x5b48b8
0x4189a0:       test   %rdi,%rdi
0x4189a3:       jne    0x418bee
0x4189a9:       mov    1687304(%rip),%rdi        # 0x5b48b8
0x4189b0:       callq  0x417380
(gdb)
For this case, I don't know how to debug it accord to these information!

Example 4

Aim: for dead-lock case. 
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

pthread_t ntid;

class Mutex
{
public:
    Mutex(bool recursive = false) {
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr,
        recursive ?  PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_ERRORCHECK );
    pthread_mutex_init(&d_mutex, &attr);
    pthread_mutexattr_destroy(&attr);
    }
    ~Mutex() { pthread_mutex_destroy(&d_mutex); }

    void Lock() { pthread_mutex_lock(&d_mutex); }
    void Lock_Cancel() {  pthread_testcancel(); pthread_mutex_lock(&d_mutex); }
    void Unlock() { pthread_mutex_unlock(&d_mutex); }
    bool TryLock() { return pthread_mutex_trylock(&d_mutex) == 0; }

private:
    pthread_mutex_t d_mutex;
};

void printids(const char *s)
{
    pid_t       pid;
    pthread_t   tid;

    pid = getpid();
    tid = pthread_self();
    printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int)pid,
            (unsigned int)tid, (unsigned int)tid);
}

Mutex locker, locker2;

void * thr_fn(void *arg)
{
    int count = 1000;
    if(arg != NULL)
        count = *((int*)arg);

    locker.Lock();
    int i=0;
    for(i=0; i<count; ++i)
    {
        printf("Func 1 Time %d : ", i);
        locker2.Lock();
        printids("new thread: ");
        sleep(1);
        locker2.Unlock();
    }

    locker.Unlock();
    return((void *)0);
}

int main(void)
{
    int err;
    pthread_t tid1, tid2;
    void* tret;

    int count = 10;

    printf("PID=%d\n", getpid());
    // thread 1
    err = pthread_create(&tid1, NULL, thr_fn, NULL);
    if (err != 0)
    {
        printf("can't create thread : %s\n", strerror(err));
    }
    printf("Create thread 1 : %u \n", (unsigned int)tid1);

    // thread 2
    err = pthread_create(&tid2, NULL, thr_fn, &count);
    if (err != 0)
    {
        printf("can't create thread : %s\n", strerror(err));
    }
    printf("Create thread 2 : %u \n", (unsigned int)tid2);

    printids("main thread:");
    sleep(1);

    pthread_cancel(tid1);
    printf("Cancel thread 1\n");

    err = pthread_join(tid1, &tret);
    if (err != 0)
        printf("can't join with thread 1: %s\n", strerror(err));

printf("thread 1 exit code %d\n", (int)tret);
    err = pthread_join(tid2, &tret);
    if (err != 0)
        printf("can't join with thread 2: %s\n", strerror(err));

    printf("thread 2 exit code %d\n", (int)tret);

    return 0;
}
g++ -o test deadlock.cc –lpthread
(shell 1)nochen@bclnx64 ~/test$ ./test  
PID=4249
Create thread 1 : 1084229984
Create thread 2 : 1094719840
main thread: pid 4249 tid 2505602208 (0x955874a0)
Func 1 Time 0 : new thread:  pid 4249 tid 1084229984 (0x40a00960)
Cancel thread 1
thread 1 exit code -1
 
(shell 2)gdb ./test
(gdb) attach 4249
(gdb) info thread
  2 Thread 1094719840 (LWP 4251)  0x0000003cf620adfb in __lll_mutex_lock_wait () from /lib64/tls/libpthread.so.0
  1 Thread 182894228640 (LWP 4249)  0x0000003cf6206ffb in pthread_join () from /lib64/tls/libpthread.so.0
(gdb) bt
#0  0x0000003cf6206ffb in pthread_join () from /lib64/tls/libpthread.so.0
#1  0x0000000000400d8e in main ()
(gdb) thread 2
[Switching to thread 2 (Thread 1094719840 (LWP 4251))]#0  0x0000003cf620adfb in __lll_mutex_lock_wait ()
   from /lib64/tls/libpthread.so.0
(gdb) bt
#0  0x0000003cf620adfb in __lll_mutex_lock_wait () from /lib64/tls/libpthread.so.0
#1  0x00000000414011e0 in ?? ()
#2  0x00000000414019f0 in ?? ()
#3  0x0000003cf6207bd4 in pthread_mutex_lock () from /lib64/tls/libpthread.so.0
#4  0x0000000000000000 in ?? ()
(gdb) info register
rax            0xfffffffffffffffc       -4
rbx            0x0      0
rcx            0xffffffffffffffff       -1
rdx            0x2      2
rsi            0x0      0
rdi            0x501740 5248832
rbp            0x414011b0       0x414011b0
rsp            0x41401100       0x41401100
rip            0x3cf620adfb     0x3cf620adfb <__lll_mutex_lock_wait+27>
eflags         0x202    514
 (gdb) x/16gx 0x414011b0 - 16
0x414011a0:     0x0000000000000000      0x0000000000501740
0x414011b0:     0x00000000414011d0      0x0000000000400b4d
0x414011c0:     0x0000000a00000000      0x0000007fbffff3cc
0x414011d0:     0x0000000000000000      0x0000003cf620610a (not useful information)
0x414011e0:     0x0000000000000000      0x0000000041401960
0x414011f0:     0x0000000041401960      0x0000000000000000
0x41401200:     0x0000003cf6206080      0x0000003cf620d4e0
0x41401210:     0x0000000000000000      0x0000003cf620d4e0
(gdb) x/32i 0x0000000000400b4d - 4
0x400b49 <_Z6thr_fnPv+41>:      push   %rbx
0x400b4a <_Z6thr_fnPv+42>:      add    (%rax),%eax
0x400b4c <_Z6thr_fnPv+44>:      add    %al,%bh
0x400b4e <_Z6thr_fnPv+46>:      rexXZ lock add %al,(%rax)
0x400b52 <_Z6thr_fnPv+50>:      add    %al,(%rax)
0x400b54 <_Z6thr_fnPv+52>:      movl   $0x0,0xfffffffffffffff0(%rbp)
0x400b5b <_Z6thr_fnPv+59>:      mov    0xfffffffffffffff0(%rbp),%eax
0x400b5e <_Z6thr_fnPv+62>:      cmp    0xfffffffffffffff4(%rbp),%eax
0x400b61 <_Z6thr_fnPv+65>:      jge    0x400ba5 <_Z6thr_fnPv+133>
0x400b63 <_Z6thr_fnPv+67>:      mov    0xfffffffffffffff0(%rbp),%esi
0x400b66 <_Z6thr_fnPv+70>:      mov    $0x401035,%edi
0x400b6b <_Z6thr_fnPv+75>:      mov    $0x0,%eax
 
From these information, we can know that the dead-lock is in function thr_fnPv+44 and thr_fnPv+46。 Thus we know it is because thread 2(1094719840) can’t get lock!
 

Example 5

Aim: for dead-lock case. 
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

pthread_t ntid;

class Mutex
{
public:
    Mutex(bool recursive = false) {
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr,
        recursive ?  PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_ERRORCHECK );
    pthread_mutex_init(&d_mutex, &attr);
    pthread_mutexattr_destroy(&attr);
    }
    ~Mutex() { pthread_mutex_destroy(&d_mutex); }

    void Lock() { pthread_mutex_lock(&d_mutex); }
    void Lock_Cancel() {  pthread_testcancel(); pthread_mutex_lock(&d_mutex); }
    void Unlock() { pthread_mutex_unlock(&d_mutex); }
    bool TryLock() { return pthread_mutex_trylock(&d_mutex) == 0; }

private:
    pthread_mutex_t d_mutex;
};

void printids(const char *s)
{
    pid_t       pid;
    pthread_t   tid;

    pid = getpid();
    tid = pthread_self();
    printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int)pid,
            (unsigned int)tid, (unsigned int)tid);
}

Mutex locker, locker2;

void * thr_fn(void *arg)
{
    int count = 1000;
    if(arg != NULL)
        count = *((int*)arg);

    locker.Lock();
    int i=0;
    for(i=0; i<count; ++i)
    {
        printf("Func 1 Time %d : ", i);
        locker2.Lock();
        printids("new thread: ");
        sleep(1);
        locker2.Unlock();
    }

    locker.Unlock();
    return((void *)0);
}


void * thr_fn2(void *arg)
{
    int count = 1000;
    if(arg != NULL)
        count = *((int*)arg);

    locker2.Lock();
    int i=0;
    for(i=0; i<count; ++i)
    {
        printf("Func2 Time %d : ", i);
        locker.Lock();
        printids("new thread: ");
        sleep(1);
        locker.Unlock();
    }

    locker2.Unlock();

    return((void *)0);
}


int main(void)
{
    int err;
    pthread_t tid1, tid2;
    void* tret;

    int count = 10;

    printf("PID=%d\n", getpid());
    // thread 1
    err = pthread_create(&tid1, NULL, thr_fn, NULL);
    if (err != 0)
    {
        printf("can't create thread : %s\n", strerror(err));
    }
    printf("Create thread 1 : %u \n", (unsigned int)tid1);

    // thread 2
    err = pthread_create(&tid2, NULL, thr_fn2, &count);
    if (err != 0)
    {
        printf("can't create thread : %s\n", strerror(err));
    }
    printf("Create thread 2 : %u \n", (unsigned int)tid2);

    printids("main thread:");
    sleep(1);

    // pthread_cancel(tid1);
    // printf("Cancel thread 1\n");

    err = pthread_join(tid1, &tret);
    if (err != 0)
        printf("can't join with thread 1: %s\n", strerror(err));

    printf("thread 1 exit code %d\n", (int)tret);

    // thread 2
    /* err = pthread_create(&tid2, NULL, thr_fn, &count);
    if (err != 0)
    {
        printf("can't create thread : %s\n", strerror(err));
    }
    printf("Create thread 2 : %u \n", (unsigned int)tid2);      */

    ////////////////////////////////
    err = pthread_join(tid2, &tret);
    if (err != 0)
        printf("can't join with thread 2: %s\n", strerror(err));

    printf("thread 2 exit code %d\n", (int)tret);

    return 0;
}
Shell 1:
g++ -g -o test deadlock.cc –lpthread
nochen@bclnx64 ~/test$ ./test
PID=6283
Create thread 1 : 1084229984
Create thread 2 : 1094719840
main thread: pid 6283 tid 2505602208 (0x955874a0)
Func 1 Time 0 : new thread:  pid 6283 tid 1084229984 (0x40a00960)
 
Shell 2:
gdb ./test
(gdb) attach 6283
(gdb) info thread
  3 Thread 1084229984 (LWP 6284)  0x0000003cf620adfb in __lll_mutex_lock_wait () from /lib64/tls/libpthread.so.0
  2 Thread 1094719840 (LWP 6285)  0x0000003cf620adfb in __lll_mutex_lock_wait () from /lib64/tls/libpthread.so.0
* 1 Thread 182894228640 (LWP 6283)  0x0000003cf6206ffb in pthread_join () from /lib64/tls/libpthread.so.0
(gdb) thread 2
[Switching to thread 2 (Thread 1094719840 (LWP 6285))]#0  0x0000003cf620adfb in __lll_mutex_lock_wait ()
   from /lib64/tls/libpthread.so.0
(gdb) info register
rax            0xfffffffffffffffc       -4
rbx            0x0      0
rcx            0xffffffffffffffff       -1
rdx            0x2      2
rsi            0x0      0
rdi            0x5016a0 5248672
rbp            0x414011b0       0x414011b0
rsp            0x41401100       0x41401100
rip            0x3cf620adfb     0x3cf620adfb <__lll_mutex_lock_wait+27>
eflags         0x202    514
 (gdb) x/32gx 0x414011b0 - 16
0x414011a0:     0x0000000000000000      0x00000000005016a0
0x414011b0:     0x00000000414011d0      0x0000000000400bc5
0x414011c0:     0x0000000a00000000      0x0000007fbffff3cc
0x414011d0:     0x0000000000000000      0x0000003cf620610a
0x414011e0:     0x0000000000000000      0x0000000041401960
0x414011f0:     0x0000000041401960      0x0000000000000000
(gdb) x/32i 0x0000000000400bc5 - 2
0x400bc3 <_Z7thr_fn2Pv+93>:     add    %al,(%rax)
0x400bc5 <_Z7thr_fn2Pv+95>:     mov    $0x400fd7,%edi
0x400bca <_Z7thr_fn2Pv+100>:    callq  0x400a88 <_Z8printidsPKc>
0x400bcf <_Z7thr_fn2Pv+105>:    mov    $0x1,%edi
0x400bd4 <_Z7thr_fn2Pv+110>:    callq  0x400938
0x400bd9 <_Z7thr_fn2Pv+115>:    mov    $0x5016a0,%edi
0x400bde <_Z7thr_fn2Pv+120>:    callq  0x400e20 <_ZN5Mutex6UnlockEv>
0x400be3 <_Z7thr_fn2Pv+125>:    lea    0xfffffffffffffff0(%rbp),%rax
0x400be7 <_Z7thr_fn2Pv+129>:    incl   (%rax)
0x400be9 <_Z7thr_fn2Pv+131>:    jmp    0x400ba1 <_Z7thr_fn2Pv+59>
0x400beb <_Z7thr_fn2Pv+133>:    mov    $0x5016e0,%edi
0x400bf0 <_Z7thr_fn2Pv+138>:    callq  0x400e20 <_ZN5Mutex6UnlockEv>
0x400bf5 <_Z7thr_fn2Pv+143>:    mov    $0x0,%eax
0x400bfa <_Z7thr_fn2Pv+148>:    leaveq
0x400bfb <_Z7thr_fn2Pv+149>:    retq
(gdb) thread 3
[Switching to thread 3 (Thread 1084229984 (LWP 6284))]#0  0x0000003cf620adfb in __lll_mutex_lock_wait ()
   from /lib64/tls/libpthread.so.0
(gdb) info register
rax            0xfffffffffffffffc       -4
rbx            0x0      0
rcx            0xffffffffffffffff       -1
rdx            0x2      2
rsi            0x0      0
rdi            0x5016e0 5248736
rbp            0x40a001b0       0x40a001b0
rsp            0x40a00100       0x40a00100
rip            0x3cf620adfb     0x3cf620adfb <__lll_mutex_lock_wait+27>
eflags         0x202    514
(gdb) x/16gx 0x40a001b0 - 16
0x40a001a0:     0x0000000040a001d0      0x00000000005016e0
0x40a001b0:     0x0000000040a001d0      0x0000000000400b2f
0x40a001c0:     0x000003e800000001      0x0000000000000000
0x40a001d0:     0x0000000000000000      0x0000003cf620610a
0x40a001e0:     0x0000000000000000      0x0000000040a00960
0x40a001f0:     0x0000000040a00960      0x0000000000000000
0x40a00200:     0x0000003cf6206080      0x0000003cf620d4e0
0x40a00210:     0x0000000000000000      0x0000003cf620d4e0
(gdb) x/32i 0x0000000000400b2f-2
0x400b2d <_Z6thr_fnPv+93>:      add    %al,(%rax)
0x400b2f <_Z6thr_fnPv+95>:      mov    $0x400fd7,%edi
0x400b34 <_Z6thr_fnPv+100>:     callq  0x400a88 <_Z8printidsPKc>
0x400b39 <_Z6thr_fnPv+105>:     mov    $0x1,%edi
0x400b3e <_Z6thr_fnPv+110>:     callq  0x400938
0x400b43 <_Z6thr_fnPv+115>:     mov    $0x5016e0,%edi
0x400b48 <_Z6thr_fnPv+120>:     callq  0x400e20 <_ZN5Mutex6UnlockEv>
0x400b4d <_Z6thr_fnPv+125>:     lea    0xfffffffffffffff0(%rbp),%rax
0x400b51 <_Z6thr_fnPv+129>:     incl   (%rax)
0x400b53 <_Z6thr_fnPv+131>:     jmp    0x400b0b <_Z6thr_fnPv+59>
0x400b55 <_Z6thr_fnPv+133>:     mov    $0x5016a0,%edi
0x400b5a <_Z6thr_fnPv+138>:     callq  0x400e20 <_ZN5Mutex6UnlockEv>
0x400b5f <_Z6thr_fnPv+143>:     mov    $0x0,%eax
0x400b64 <_Z6thr_fnPv+148>:     leaveq
0x400b65 <_Z6thr_fnPv+149>:     retq
0x400b66 <_Z7thr_fn2Pv>:        push   %rbp
0x400b67 <_Z7thr_fn2Pv+1>:      mov    %rsp,%rbp
0x400b6a <_Z7thr_fn2Pv+4>:      sub    $0x10,%rsp
0x400b6e <_Z7thr_fn2Pv+8>:      mov    %rdi,0xfffffffffffffff8(%rbp)
0x400b72 <_Z7thr_fn2Pv+12>:     movl   $0x3e8,0xfffffffffffffff4(%rbp)
0x400b79 <_Z7thr_fn2Pv+19>:     cmpq   $0x0,0xfffffffffffffff8(%rbp)
0x400b7e <_Z7thr_fn2Pv+24>:     je     0x400b89 <_Z7thr_fn2Pv+35>
0x400b80 <_Z7thr_fn2Pv+26>:     mov    0xfffffffffffffff8(%rbp),%rax
0x400b84 <_Z7thr_fn2Pv+30>:     mov    (%rax),%eax
0x400b86 <_Z7thr_fn2Pv+32>:     mov    %eax,0xfffffffffffffff4(%rbp)
0x400b89 <_Z7thr_fn2Pv+35>:     mov    $0x5016e0,%edi
0x400b8e <_Z7thr_fn2Pv+40>:     callq  0x400e38 <_ZN5Mutex4LockEv>
0x400b93 <_Z7thr_fn2Pv+45>:     movl   $0x0,0xfffffffffffffff0(%rbp)
0x400b9a <_Z7thr_fn2Pv+52>:     movl   $0x0,0xfffffffffffffff0(%rbp)
0x400ba1 <_Z7thr_fn2Pv+59>:     mov    0xfffffffffffffff0(%rbp),%eax
0x400ba4 <_Z7thr_fn2Pv+62>:     cmp    0xfffffffffffffff4(%rbp),%eax
0x400ba7 <_Z7thr_fn2Pv+65>:     jge    0x400beb <_Z7thr_fn2Pv+133>
(gdb) Quit
 Thus we know function thr_fn and thr_fn2 is dead-lock!