Làm cách nào để phân tích tệp kết xuất lõi của chương trình với GDB khi tệp có tham số dòng lệnh?


156

Chương trình của tôi hoạt động như thế này:

exe -p param1 -i param2 -o param3

Nó bị sập và tạo ra một tệp kết xuất lõi , core.pid.

Tôi muốn phân tích tệp kết xuất lõi bằng cách

gdb ./exe -p param1 -i param2 -o param3 core.pid

Nhưng GDB nhận ra các tham số của tệp EXE là đầu vào của GDB.

Làm cách nào để phân tích tệp kết xuất lõi trong tình huống này?


1
Bạn có chắc chắn exekhông phải là tập lệnh shell (để đặt một số biến, v.v.) như ví dụ như firefoxtrên Linux không?
Basile Starynkevitch

Câu trả lời:


182

Bạn có thể sử dụng lõi với GDB theo nhiều cách, nhưng việc truyền tham số được truyền cho tệp thực thi cho GDB không phải là cách sử dụng tệp lõi. Đây cũng có thể là lý do bạn gặp lỗi đó. Bạn có thể sử dụng tệp lõi theo các cách sau:

gdb <executable> <core-file>hoặc gdb <executable> -c <core-file>hoặc

gdb <executable>
...
(gdb) core <core-file>

Khi sử dụng tệp lõi, bạn không phải truyền đối số. Kịch bản sự cố được hiển thị trong GDB (được kiểm tra với GDB phiên bản 7.1 trên Ubuntu).

Ví dụ:

$ ./crash -p param1 -o param2
Segmentation fault (core dumped)
$ gdb ./crash core
GNU gdb (GDB) 7.1-ubuntu
...
Core was generated by `./crash -p param1 -o param2'. <<<<< See this line shows crash scenario
Program terminated with signal 11, Segmentation fault.
#0  __strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99    ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.
    in ../sysdeps/i386/i686/multiarch/../../i586/strlen.S
(gdb)

Nếu bạn muốn truyền tham số cho tệp thực thi được gỡ lỗi trong GDB, hãy sử dụng --args.

Ví dụ:

$ gdb --args ./crash -p param1 -o param2
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) r
Starting program: /home/@@@@/crash -p param1 -o param2

Program received signal SIGSEGV, Segmentation fault.
__strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99    ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.
    in ../sysdeps/i386/i686/multiarch/../../i586/strlen.S
(gdb)

Các trang hướng dẫn sẽ hữu ích để xem các tùy chọn GDB khác.


38

Sử dụng đơn giản GDB, để gỡ lỗi các tệp coredump:

gdb <executable_path> <coredump_file_path>

Tệp coredump cho "process" được tạo dưới dạng tệp "core.pid".

Sau khi bạn vào bên trong dấu nhắc GDB (khi thực hiện lệnh trên), hãy nhập:

...
(gdb) where

Điều này sẽ giúp bạn có được thông tin của ngăn xếp, nơi bạn có thể phân tích nguyên nhân của sự cố / lỗi. Lệnh khác, cho cùng mục đích là:

...
(gdb) bt full

Điều này giống như trên. Theo quy ước, nó liệt kê toàn bộ thông tin ngăn xếp (cuối cùng dẫn đến vị trí sự cố).


22

Chỉ cần bỏ qua các tham số. GDB không cần chúng:

gdb ./exe core.pid

Nhưng điều này không làm việc. Cảnh báo đầu ra gdb: tệp lõi có thể không khớp với tệp thực thi được chỉ định. Không thể đọc hình ảnh tệp đối tượng hợp lệ từ bộ nhớ.
Treper

6
"tập tin lõi có thể không phù hợp với thực thi được chỉ định". Bạn đã sửa đổi exe sau khi nó tạo ra lõi? Bạn có thể xây dựng lại nó với các tùy chọn dòng lệnh khác nhau? Điều rất quan trọng là cung cấp cho GDB chính xác nhị phân đã tạo ra lõi. Nếu bạn không, bạn sẽ nhận được rác.
Sử dụng tiếng Nga

2
Cũng đảm bảo rằng nhị phân được truyền cho gdb không bị tước. Bạn có thể chạy 'tệp <tên nhị phân>' cho thấy nó bị tước hay không.
Diwakar Sharma

12

objdump+ gdbví dụ chạy tối thiểu

TL; DR:

Bây giờ cho các thiết lập kiểm tra giáo dục đầy đủ:

C chính

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int myfunc(int i) {
    *(int*)(NULL) = i; /* line 7 */
    return i - 1;
}

int main(int argc, char **argv) {
    /* Setup some memory. */
    char data_ptr[] = "string in data segment";
    char *mmap_ptr;
    char *text_ptr = "string in text segment";
    (void)argv;
    mmap_ptr = (char *)malloc(sizeof(data_ptr) + 1);
    strcpy(mmap_ptr, data_ptr);
    mmap_ptr[10] = 'm';
    mmap_ptr[11] = 'm';
    mmap_ptr[12] = 'a';
    mmap_ptr[13] = 'p';
    printf("text addr: %p\n", text_ptr);
    printf("data addr: %p\n", data_ptr);
    printf("mmap addr: %p\n", mmap_ptr);

    /* Call a function to prepare a stack trace. */
    return myfunc(argc);
}

Biên dịch và chạy để tạo lõi:

gcc -ggdb3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
ulimit -c unlimited
rm -f core
./main.out

Đầu ra:

text addr: 0x4007d4
data addr: 0x7ffec6739220
mmap addr: 0x1612010
Segmentation fault (core dumped)

GDB chỉ cho chúng tôi dòng chính xác xảy ra lỗi phân đoạn, đây là điều mà hầu hết người dùng muốn trong khi gỡ lỗi:

gdb -q -nh main.out core

sau đó:

Reading symbols from main.out...done.
[New LWP 27479]
Core was generated by `./main.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000000000400635 in myfunc (i=1) at main.c:7
7           *(int*)(NULL) = i;
(gdb) bt
#0  0x0000000000400635 in myfunc (i=1) at main.c:7
#1  0x000000000040072b in main (argc=1, argv=0x7ffec6739328) at main.c:28

trong đó chỉ chúng tôi trực tiếp đến dòng lỗi 7.

Đối số CLI được lưu trữ trong tệp lõi và không cần phải truyền lại

Để trả lời các câu hỏi đối số CLI cụ thể, chúng tôi thấy rằng nếu chúng tôi thay đổi các đối số cli, ví dụ như với:

rm -f core
./main.out 1 2

sau đó, điều này sẽ được phản ánh trong bactrace trước mà không có bất kỳ thay đổi nào trong các lệnh của chúng tôi:

Reading symbols from main.out...done.
[New LWP 21838]
Core was generated by `./main.out 1 2'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000564583cf2759 in myfunc (i=3) at main.c:7
7           *(int*)(NULL) = i; /* line 7 */
(gdb) bt
#0  0x0000564583cf2759 in myfunc (i=3) at main.c:7
#1  0x0000564583cf2858 in main (argc=3, argv=0x7ffcca4effa8) at main.c:2

Vì vậy, lưu ý làm thế nào bây giờ argc=3. Do đó, điều này có nghĩa là tệp lõi lưu trữ thông tin đó. Tôi đoán nó chỉ lưu trữ nó như là đối số của main, giống như nó lưu trữ các đối số của bất kỳ chức năng nào khác.

Điều này có ý nghĩa nếu bạn xem xét rằng kết xuất lõi phải được lưu trữ toàn bộ bộ nhớ và trạng thái đăng ký của chương trình, và do đó, nó có tất cả thông tin cần thiết để xác định giá trị của các đối số hàm trên ngăn xếp hiện tại.

Ít rõ ràng hơn là cách kiểm tra các biến môi trường: Cách lấy biến môi trường từ kết xuất lõi Các biến môi trường cũng có trong bộ nhớ để objdump có chứa thông tin đó, nhưng tôi không chắc cách liệt kê tất cả chúng một cách thuận tiện , từng người một như sau đã làm bài kiểm tra của tôi:

p __environ[0]

Phân tích Binutils

Bằng cách sử dụng các công cụ binutils như readelfobjdump, chúng ta có thể kết xuất hàng loạt thông tin có trong coretệp như trạng thái bộ nhớ.

Hầu hết / tất cả cũng phải được hiển thị thông qua GDB, nhưng các công cụ binutils đó cung cấp một cách tiếp cận số lượng lớn hơn, thuận tiện cho các trường hợp sử dụng nhất định, trong khi GDB thuận tiện hơn cho việc khám phá tương tác nhiều hơn.

Đầu tiên:

file core

cho chúng ta biết rằng coretệp thực sự là tệp ELF :

core: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './main.out'

đó là lý do tại sao chúng ta có thể kiểm tra nó trực tiếp hơn bằng các công cụ binutils thông thường.

Nhìn nhanh vào tiêu chuẩn ELF cho thấy thực sự có một loại ELF dành riêng cho nó:

Elf32_Ehd.e_type == ET_CORE

Thông tin định dạng khác có thể được tìm thấy tại:

man 5 core

Sau đó:

readelf -Wa core

đưa ra một số gợi ý về cấu trúc tập tin. Bộ nhớ dường như được chứa trong các tiêu đề chương trình thông thường:

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  NOTE           0x000468 0x0000000000000000 0x0000000000000000 0x000b9c 0x000000     0
  LOAD           0x002000 0x0000000000400000 0x0000000000000000 0x001000 0x001000 R E 0x1000
  LOAD           0x003000 0x0000000000600000 0x0000000000000000 0x001000 0x001000 R   0x1000
  LOAD           0x004000 0x0000000000601000 0x0000000000000000 0x001000 0x001000 RW  0x1000

và có thêm một số siêu dữ liệu trong khu vực ghi chú, đáng chú ý prstatuscó chứa PC :

Displaying notes found at file offset 0x00000468 with length 0x00000b9c:
  Owner                 Data size       Description
  CORE                 0x00000150       NT_PRSTATUS (prstatus structure)
  CORE                 0x00000088       NT_PRPSINFO (prpsinfo structure)
  CORE                 0x00000080       NT_SIGINFO (siginfo_t data)
  CORE                 0x00000130       NT_AUXV (auxiliary vector)
  CORE                 0x00000246       NT_FILE (mapped files)
    Page size: 4096
                 Start                 End         Page Offset
    0x0000000000400000  0x0000000000401000  0x0000000000000000
        /home/ciro/test/main.out
    0x0000000000600000  0x0000000000601000  0x0000000000000000
        /home/ciro/test/main.out
    0x0000000000601000  0x0000000000602000  0x0000000000000001
        /home/ciro/test/main.out
    0x00007f8d939ee000  0x00007f8d93bae000  0x0000000000000000
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93bae000  0x00007f8d93dae000  0x00000000000001c0
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93dae000  0x00007f8d93db2000  0x00000000000001c0
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93db2000  0x00007f8d93db4000  0x00000000000001c4
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93db8000  0x00007f8d93dde000  0x0000000000000000
        /lib/x86_64-linux-gnu/ld-2.23.so
    0x00007f8d93fdd000  0x00007f8d93fde000  0x0000000000000025
        /lib/x86_64-linux-gnu/ld-2.23.so
    0x00007f8d93fde000  0x00007f8d93fdf000  0x0000000000000026
        /lib/x86_64-linux-gnu/ld-2.23.so
  CORE                 0x00000200       NT_FPREGSET (floating point registers)
  LINUX                0x00000340       NT_X86_XSTATE (x86 XSAVE extended state)

objdump có thể dễ dàng kết xuất tất cả bộ nhớ với:

objdump -s core

trong đó có:

Contents of section load1:

 4007d0 01000200 73747269 6e672069 6e207465  ....string in te
 4007e0 78742073 65676d65 6e740074 65787420  xt segment.text 

Contents of section load15:

 7ffec6739220 73747269 6e672069 6e206461 74612073  string in data s
 7ffec6739230 65676d65 6e740000 00a8677b 9c6778cd  egment....g{.gx.

Contents of section load4:

 1612010 73747269 6e672069 6e206d6d 61702073  string in mmap s
 1612020 65676d65 6e740000 11040000 00000000  egment..........

phù hợp chính xác với giá trị xuất chuẩn trong lần chạy của chúng tôi.

Điều này đã được thử nghiệm trên Ubuntu 16.04 amd64, GCC 6.4.0 và binutils 2.26.1.


10

Từ hướng dẫn gỡ lỗi GDB của RMS :

prompt > myprogram
Segmentation fault (core dumped)
prompt > gdb myprogram
...
(gdb) core core.pid
...

Hãy chắc chắn rằng tập tin của bạn thực sự là một corehình ảnh - kiểm tra nó bằng cách sử dụng file.


9

Một cách tiếp cận hơi khác nhau sẽ cho phép bạn bỏ qua hoàn toàn GDB. Nếu tất cả những gì bạn muốn là một backtrace, tiện ích dành riêng cho Linux 'Catchsegv' sẽ bắt SIGSEGV và hiển thị một backtrace.


3

Nó không quan trọng nếu thực thi có tranh luận hay không. Để chạy GDB trên bất kỳ tệp nhị phân nào với tệp lõi được tạo, cú pháp bên dưới.

Syntax:
gdb <binary name> <generated core file>
Eg:
gdb l3_entity 6290-corefile

Hãy để tôi lấy ví dụ dưới đây để hiểu thêm.

bash-4.1$ **gdb l3_entity 6290-corefile**

**Core was generated** by `/dir1/dir2/dir3/l3_entity **Program terminated with signal SIGABRT, Aborted.**
#0
#1
#2
#3
#4
#5
#6
#7
#8
#9
#10
(gdb)

Từ đầu ra trên, bạn có thể đoán được điều gì đó về lõi, cho dù đó là truy cập NULL, SIGABORT, v.v.

Các số # 0 đến # 10 này là các khung ngăn xếp của GDB. Những khung ngăn xếp này không phải là nhị phân của bạn. Trong 0 - 10 khung hình trên nếu bạn nghi ngờ có gì sai, hãy chọn khung đó

(gdb) frame 8

Bây giờ để xem chi tiết hơn về nó:

(gdb) list +

Để điều tra vấn đề hơn nữa, bạn có thể in các giá trị biến bị nghi ngờ tại thời điểm này.

(gdb) print thread_name

0

Chỉ cần gõ lệnh:

$ gdb <Binary> <codeDump>

Hoặc là

$ gdb <binary>

$ gdb) core <coreDump>

Không cần phải cung cấp bất kỳ đối số dòng lệnh nào. Các kết xuất mã được tạo ra do một bài tập trước đó.


-1

Bạn có thể phân tích tệp kết xuất lõi bằng lệnh "gdb".

 gdb - The GNU Debugger

 syntax:

 # gdb executable-file core-file

 example: # gdb out.txt core.xxx 

1
out.txt là một tập tin thực thi? Điều đó có vẻ như một phần mở rộng tập tin sai lệch.
Alan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.