Tại sao GDB cần thực thi cũng như kết xuất lõi?


11

Tôi đang gỡ lỗi bằng cách sử dụng các bãi chứa lõi và lưu ý rằng gdb cần bạn cung cấp tệp thực thi cũng như kết xuất lõi. Tại sao lại thế này? Nếu kết xuất lõi chứa tất cả bộ nhớ mà quy trình sử dụng, không phải tệp thực thi có trong kết xuất lõi không? Có lẽ không có gì đảm bảo rằng toàn bộ exe được tải vào bộ nhớ (các tệp thực thi riêng lẻ thường không lớn như vậy) hoặc có thể kết xuất lõi không chứa tất cả bộ nhớ có liên quan? Có phải là cho các biểu tượng (có lẽ chúng không được tải vào bộ nhớ thông thường)?


1
Tệp thực thi chứa thông tin ký hiệu, như được ghi chú trong tài liệu gdb ...
Thomas Dickey

1
Đáng ngạc nhiên, không có câu trả lời (ngoại trừ câu tôi vừa thêm) đề cập đến định dạng DWARF
Basile Starynkevitch

Câu trả lời:


15

Kết xuất lõi chỉ là kết xuất của bộ nhớ chương trình của bạn, nếu bạn biết mọi thứ ở đâu thì bạn có thể sử dụng nó.

Bạn sử dụng tệp thực thi vì nó giải thích nơi (về mặt địa chỉ logic) mọi thứ được đặt trong bộ nhớ, tức là tệp lõi.

Nếu bạn sử dụng một lệnh, objdumpnó sẽ kết xuất dữ liệu meta về đối tượng thực thi mà bạn đang điều tra. Sử dụng một đối tượng thực thi có tên a.out làm ví dụ.

objdump -h a.outchỉ bỏ thông tin tiêu đề, bạn sẽ thấy các phần có tên, vd. .data hoặc .bss hoặc .text (còn nhiều nữa). Chúng thông báo cho trình tải hạt nhân trong đó trong các đối tượng có thể tìm thấy các phần khác nhau và ở đâu trong không gian địa chỉ tiến trình, phần đó sẽ được tải và đối với một số phần (ví dụ .data .text) những gì sẽ được tải. (phần .bss không chứa bất kỳ dữ liệu nào trong tệp nhưng nó đề cập đến dung lượng bộ nhớ dự trữ trong quy trình cho dữ liệu chưa được khởi tạo, nó chứa đầy các số không).

Bố cục của tệp đối tượng thực thi tuân theo tiêu chuẩn, ELF.

objdump -x a.out - vứt bỏ mọi thứ

Nếu đối tượng thực thi vẫn chứa các bảng ký hiệu của nó (nó chưa bị tước - man stripvà bạn đã sử dụng -gđể tạo thế hệ gỡ lỗi để gcc giả sử biên dịch nguồn ac), thì bạn có thể kiểm tra nội dung cốt lõi bằng tên ký hiệu, ví dụ: nếu bạn có biến / bộ đệm có tên inputLine trong mã nguồn của bạn, bạn có thể sử dụng tên đó gdbđể xem nội dung của nó. tức là gdbsẽ biết phần bù từ khi bắt đầu phân đoạn dữ liệu khởi tạo chương trình của bạn nơi inputLine bắt đầu và độ dài của biến đó.

Đọc thêm Điều 1 , Điều 2 , và để biết thông số kỹ thuật Định dạng liên kết và định dạng thực thi (ELF) gritty gritty .


Cập nhật sau khi bình luận @mirabilos bên dưới.

Nhưng nếu sử dụng bảng ký hiệu như trong

$ gdb --batch -s a.out -c core -q -ex "x buf1"

Sản xuất

 0x601060 <buf1>:    0x72617453

và sau đó không sử dụng bảng ký hiệu và kiểm tra địa chỉ trực tiếp trong,

$ gdb --batch -c core -q -ex "x 0x601060"

Sản xuất

0x601060:   0x72617453

Tôi đã kiểm tra bộ nhớ trực tiếp mà không sử dụng bảng ký hiệu trong lệnh thứ 2.


Tôi cũng thấy, câu trả lời của @ user580082 thêm vào phần giải thích và sẽ bỏ phiếu.


6
Chưa bao giờ nghe nói về "phần ngăn xếp cơ bản". .bss là (theo lịch sử) "khối bắt đầu bằng ký hiệu" và thực tế là "dữ liệu được đơn vị hóa", trong khi .data là "dữ liệu khởi tạo" và văn bản (không phải .code) được sử dụng để lưu trữ mã máy. Không có phần ngăn xếp trong một nhị phân, vì ngăn xếp được tạo ra trong thời gian chạy.
jlliagre

Nếu bạn biết mọi thứ ở đâu thì bạn cũng có thể sử dụng, điều đó cũng không đúng vì không phải mọi thứ trong chương trình đều nhất thiết phải có trong dấu chân.
mirabilos

1
@jlliagre bạn đúng, tôi gọi nhầm .text .code (vì tôi đang nghĩ một lời giải thích trong khi soạn câu trả lời) - đã cập nhật. Tôi đã nhầm tưởng bss không chính xác bằng tên và đã cập nhật câu trả lời của mình, nhưng đã tránh * Chặn bởi Biểu tượng vì tôi không nghĩ nó thực sự bổ sung vào phương trình và đã giải thích nó được sử dụng như dữ liệu chưa được khởi tạo, đó là dữ liệu của chúng tôi hiểu biết chung. Cảm ơn bạn - Tôi đánh giá cao bình luận của bạn để sửa bài đăng này.
X Tian

4

Tệp lõi là một ảnh chụp nhanh của hình ảnh ngăn xếp, ánh xạ bộ nhớ và các thanh ghi tại thời điểm kết thúc quá trình. Nội dung có thể được thao tác như được đưa ra trong trang man cốt lõi . Theo ánh xạ riêng tư mặc định, ánh xạ được chia sẻ và thông tin tiêu đề ELF được đổ vào tệp lõi.

Đến với câu hỏi của bạn , lý do mà gdb yêu cầu thực thi là vì nó không mô phỏng việc thực thi, bằng cách đọc và giải thích các hướng dẫn nhị phân như valgrind, thay vào đó, nó trở thành cha mẹ của quá trình để kiểm soát hành vi của quá trình trong khi chạy thời gian. Nó sử dụng tệp lõi để xác định ánh xạ bộ nhớ và trạng thái xử lý của quá trình trong khi gặp sự cố.

Trong Linux, các tiến trình cha mẹ có thể nhận thêm thông tin về con cái của chúng, đặc biệt là khả năng tạo ra chúng cho phép trình gỡ lỗi truy cập thông tin cấp thấp của quá trình như đọc / ghi bộ nhớ, đăng ký, thay đổi ánh xạ tín hiệu, dừng thực thi, v.v.

Bạn sẽ hiểu yêu cầu của thanh tra thực thi là có tệp lõi hơn khi bạn đọc cách bất kỳ trình gỡ lỗi nào hoạt động.


1

(ngoài các câu trả lời hay khác)

Trên các hệ thống Linux hiện đại (và nhiều hệ thống tương tự Unix), thông tin gỡ lỗi (bao gồm dữ liệu meta về các loại ký hiệu, vị trí mã nguồn, loại biến, v.v ....) ở định dạng DWARF và nằm trong tệp thực thi ELF ( hoặc thư viện chia sẻ ELF) khi nó được biên dịch với một số -gtùy chọn. Tôi khuyên bạn nên biên dịch các chương trình để được gỡ lỗi -g3 -O0và có lẽ -fno-inlinenếu sử dụng GCC gần đây ; tuy nhiên, với GCC, bạn thậm chí có thể biên dịch với cả thông tin tối ưu hóa và gỡ lỗi, ví dụ như -O2 -g1, mặc dù thông tin gỡ lỗi có thể hơi "mờ" (điều này có thể giúp bắt được một số Heisenbugs nghịch ngợm ).

Sẽ khá hợp lý để tránh đưa thông tin đó vào các tệp lõi , bởi vì bạn có thể có nhiều tệp lõi khác nhau (hãy tưởng tượng một phần mềm được sử dụng rộng rãi với nhiều người dùng tạo báo cáo lỗi, hầu hết đều có corekết xuất) cho cùng một tệp thực thi. Ngoài ra, các tệp lõi (5) được kết xuất bởi kernel, điều này không quan tâm đến sự tồn tại của các phần DWARF trong các tệp thực thi elf (5) (vì các phần này không được ánh xạ vào không gian địa chỉ ảo của quá trình lỗi đã đổ lõi vào một số tín hiệu ( 7) ). Thậm chí có khả năng thông tin gỡ lỗi được đặt trong các tệp riêng biệt (bên ngoài tệp thực thi).

BTW, GDB có thể được sử dụng một cách đau đớn để gỡ lỗi các kết xuất lõi cho các tệp thực thi mà không có bất kỳ thông tin gỡ lỗi nào. Nhưng sau đó bạn thực tế gỡ lỗi ở cấp mã máy (không phải ở cấp biểu tượng được cung cấp bởi các ngôn ngữ lập trình và trình biên dịch của chúng).

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.