Sử dụng gdb để mã lắp ráp một bước bên ngoài tệp thực thi được chỉ định gây ra lỗi "không thể tìm thấy giới hạn của chức năng hiện tại"


86

Tôi đang ở bên ngoài mục tiêu thực thi của gdb và tôi thậm chí không có ngăn xếp tương ứng với mục tiêu đó. Tôi vẫn muốn thực hiện từng bước một để có thể xác minh điều gì đang xảy ra trong mã lắp ráp của mình, bởi vì tôi không phải là chuyên gia về lắp ráp x86. Thật không may, gdb từ chối thực hiện gỡ lỗi cấp lắp ráp đơn giản này. Nó cho phép tôi đặt và dừng ở điểm ngắt thích hợp, nhưng ngay sau khi tôi cố gắng thực hiện một bước trở đi, gdb báo lỗi "Không thể tìm thấy giới hạn của chức năng hiện tại" và EIP không thay đổi.

Chi tiết bổ sung:

Mã máy được tạo bởi các câu lệnh gcc asm và tôi đã sao chép nó vào vị trí bộ nhớ hạt nhân nơi nó đang thực thi, từ đầu ra của objdump -d. Tôi sẽ không ngại một cách đơn giản để sử dụng trình tải để tải mã đối tượng của tôi đến một địa chỉ được di dời, nhưng hãy nhớ rằng việc tải phải được thực hiện trong mô-đun hạt nhân.

Tôi cho rằng một giải pháp thay thế khác sẽ là tạo một mô-đun hạt nhân giả hoặc tệp thông tin gỡ lỗi để cung cấp cho gdb, để khiến nó tin rằng khu vực này nằm trong mã chương trình. gdb hoạt động tốt trên chính tệp thực thi của nhân.

(Đối với những người thực sự muốn biết, tôi đang chèn mã trong thời gian chạy vào không gian dữ liệu nhân Linux bên trong VMware VM và gỡ lỗi nó từ gdb từ xa gỡ lỗi hạt nhân thông qua sơ khai gdb tích hợp sẵn của VMware Workstation. Lưu ý rằng tôi không viết hạt nhân khai thác; Tôi là một sinh viên tốt nghiệp bảo mật đang viết một nguyên mẫu.)

(Tôi có thể đặt điểm ngắt trên mỗi lệnh bên trong lắp ráp của mình. Điều này hoạt động nhưng sẽ khá mất công sau một thời gian, vì kích thước của lệnh lắp ráp x86 khác nhau và vị trí của cụm sẽ thay đổi mỗi khi tôi khởi động lại.)


Những người thông minh trên ksplice.com đưa dữ liệu và mã vào hạt nhân bằng cách lắp ráp các mô-đun hạt nhân "giả" và tải chúng. Và nếu họ làm được thì tại sao bạn lại không thể? ;-)
ephemient

Câu trả lời:


116

Bạn có thể sử dụng stepihoặc nexti(có thể được viết tắt thành sihoặc ni) để xem qua mã máy của mình.


1
Chà. Nhìn lại, tôi không làm thế nào tôi quên được stepi. Tôi đoán tôi chỉ giả định vì gdb không có mã nguồn nên bước này sẽ hoàn nguyên về hướng dẫn lắp ráp.
Paul

1
lưu ý: bạn thường không thể gõ "break main", "run" cho các chương trình hợp ngữ. Nhập "layout asm", "start" để thay thế. Tôi nhận được điều này từ việc đọc tin nhắn dưới đây nhưng ai đó khác đọc bài đăng này có thể không kiên nhẫn.
Dmitry

1
@Dmitry starttương đương với tbreak maintheo sau là run(lưu ý: tbreakthay vì break)
Ruslan

151

Thay vì gdb, hãy chạy gdbtui. Hoặc chạy gdbbằng công -tuitắc. Hoặc nhấn C-x C-asau khi nhập gdb. Bây giờ bạn đang ở chế độ TUI của GDB .

Enter layout asmđể tạo cụm hiển thị cửa sổ phía trên - điều này sẽ tự động theo con trỏ hướng dẫn của bạn, mặc dù bạn cũng có thể thay đổi khung hoặc cuộn xung quanh trong khi gỡ lỗi. Nhấn C-x sđể vào chế độ SingleKey, trong đó, run continue up down finishv.v. được viết tắt thành một phím duy nhất, cho phép bạn xem qua chương trình của mình rất nhanh.

   + ------------------------------------------------- -------------------------- +
B +> | 0x402670 <chính> đẩy% r15 |
   | 0x402672 <main + 2> mov% edi,% r15d |
   | 0x402675 <main + 5> push% r14 |
   | 0x402677 <main + 7> push% r13 |
   | 0x402679 <main + 9> mov% rsi,% r13 |
   | 0x40267c <main + 12> push% r12 |
   | 0x40267e <main + 14> push% rbp |
   | 0x40267f <main + 15> push% rbx |
   | 0x402680 <main + 16> sub $ 0x438,% rsp |
   | 0x402687 <main + 23> mov (% rsi),% rdi |
   | 0x40268a <main + 26> movq $ 0x402a10,0x400 (% rsp) |
   | 0x402696 <main + 38> movq $ 0x0,0x408 (% rsp) |
   | 0x4026a2 <main + 50> movq $ 0x402510,0x410 (% rsp) |
   + ------------------------------------------------- -------------------------- +
tiến trình con 21518 Trong: main Dòng: ?? PC: 0x402670
(gdb) tệp / opt / j64-602 / bin / jconsole
Đọc ký hiệu từ /opt/j64-602/bin/jconsole...done.
(không tìm thấy ký hiệu gỡ lỗi) ... xong.
(gdb) bố cục asm
(gdb) bắt đầu
(gdb)

26

Điều hữu ích nhất bạn có thể làm ở đây là display/i $pc, trước khi sử dụng stepinhư đã được đề xuất trong câu trả lời của R Samuel Klatchko. Điều này yêu cầu gdb tháo rời lệnh hiện tại ngay trước khi in lời nhắc mỗi lần; thì bạn có thể tiếp tục nhấn Enter để lặp lại stepilệnh.

(Xem câu trả lời của tôi cho một câu hỏi khác để biết thêm chi tiết - bối cảnh của câu hỏi đó khác nhau, nhưng nguyên tắc thì giống nhau.)

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.