Làm thế nào để GDB tạm dừng một thực thi


16

Như bạn có thể biết, chúng ta có thể sử dụng GDB và đặt các điểm dừng trên mã của chúng tôi để tạm dừng thực thi để gỡ lỗi.

Câu hỏi của tôi là, làm thế nào để GDB tạm dừng một quá trình và cho phép bạn xem nội dung của các thanh ghi bằng cách sử dụng i rchẳng hạn. Không phải những đăng ký đang được sử dụng bởi các quá trình hệ điều hành khác liên tục? Làm thế nào để họ không bị ghi đè?

Có phải nó chỉ là một ảnh chụp nhanh của nội dung và không phải là dữ liệu trực tiếp?


2
Tại sao tất cả các thanh ghi không bị ghi đè khi HĐH quyết định tạm dừng chương trình của bạn một lát và chạy một chương trình khác?
dùng253751

CppCon 2018: Simon Nhãn hiệu “Làm thế nào C ++ Debuggers làm việc” youtube.com/watch?v=0DDrseUomfU
Robert Andrzejuk

Câu trả lời:


24

Nó thay đổi một chút theo kiến ​​trúc, nhưng những điểm quan trọng được áp dụng gần như phổ biến:

  • Dịch vụ ngắt làm cho trạng thái CPU (bao gồm các thanh ghi) được lưu vào bộ nhớ trước khi chạy ISR và được khôi phục khi ISR ​​thoát.

  • Nếu một thói quen dịch vụ ngắt hoán đổi nội dung của vị trí bộ nhớ nơi các thanh ghi đó được lưu, nó có thể thực hiện chuyển đổi ngữ cảnh . Mỗi luồng có một vùng bộ nhớ nơi các thanh ghi của nó được lưu khi luồng không chạy.

  • Công tắc ngữ cảnh được điều khiển bởi bộ lập lịch xử lý có tính đến việc một luồng đang chờ I / O, đồng bộ hóa, mức độ ưu tiên của nó là gì, phân phối tín hiệu, v.v.

  • Trình gỡ lỗi có thể tăng số lượng tạm ngưng, điều này đảm bảo luồng không chạy được. Sau đó, nó có thể kiểm tra (và thay đổi) bản sao các thanh ghi đã lưu của luồng.


14

Ngoài thông tin tuyệt vời của @BenVoigt, cho phép tôi thực hiện một số bổ sung:

Một điểm dừng được thiết lập bởi trình gỡ lỗi bằng cách thay thế giá trị mã máy (một lệnh hoặc một phần của lệnh) trong quá trình được gỡ lỗi bằng một lệnh bẫy cụ thể tại vị trí trong mã tương ứng với dòng (nguồn) mong muốn để ngắt tại. Hướng dẫn bẫy đặc biệt này có nghĩa là để sử dụng như một điểm dừng - trình gỡ lỗi biết điều này và hệ điều hành cũng vậy.

Khi tiến trình / luồng được gỡ lỗi chạm vào lệnh bẫy, điều đó kích hoạt tiến trình @Ben đang mô tả, bao gồm một nửa hoán đổi ngữ cảnh tạm dừng luồng đang chạy (bao gồm lưu trạng thái CPU vào bộ nhớ) để nối lại tiềm năng sau này. Vì bẫy này là bẫy điểm dừng, hệ điều hành giữ cho quá trình được gỡ lỗi bị treo bằng cách sử dụng có lẽ một cơ chế @Ben mô tả, và thông báo và cuối cùng tiếp tục trình gỡ lỗi.

Trình gỡ lỗi sử dụng các cuộc gọi hệ thống, sau đó, để truy cập trạng thái đã lưu của tiến trình / luồng bị treo đang được gỡ lỗi.

Để thực thi (tiếp tục) dòng mã đã bị hỏng (hiện đã có lệnh bẫy cụ thể), trình gỡ lỗi sẽ khôi phục giá trị mã máy ban đầu mà nó ghi đè bằng lệnh bẫy điểm dừng, có thể đặt bẫy khác ở một nơi khác (ví dụ: nếu bước đơn, hoặc người dùng tạo các điểm dừng mới) và đánh dấu tiến trình / luồng là có thể chạy được, có thể sử dụng cơ chế như @Ben mô tả.

Các chi tiết thực tế có thể phức tạp hơn, trong đó việc giữ một điểm dừng chạy dài bị tấn công có nghĩa là thực hiện một việc gì đó như tráo đổi bẫy điểm dừng để lấy mã thực để dòng đó có thể chạy, và sau đó hoán đổi điểm dừng lại ...

Không phải những đăng ký đang được sử dụng bởi các quá trình hệ điều hành khác liên tục? Làm thế nào để họ không bị ghi đè?

Như @Ben mô tả, sử dụng tính năng tạm dừng / tiếp tục luồng đã có (chuyển đổi ngữ cảnh / hoán đổi đa nhiệm ) cho phép bộ xử lý được chia sẻ bởi nhiều quy trình / luồng bằng cách cắt thời gian.

Có phải nó chỉ là một ảnh chụp nhanh của nội dung và không phải là dữ liệu trực tiếp?

Cả hai. Kể từ khi chủ đề đó nhấn breakpoint bị đình chỉ, nó là một bản chụp của dữ liệu trực tiếp (thanh ghi CPU, vv ..) tại thời điểm đình chỉ, và các bậc thầy có thẩm quyền của các giá trị CPU đăng ký để khôi phục lại vào bộ vi xử lý nên việc được thread tiếp tục . Nếu bạn sử dụng giao diện người dùng của trình gỡ lỗi để đọc và / hoặc thay đổi các thanh ghi CPU (của quá trình được gỡ lỗi), nó sẽ đọc và / hoặc thay đổi ảnh chụp nhanh / chủ này bằng các cuộc gọi hệ thống.


1
Vâng, hầu hết các kiến ​​trúc bộ xử lý đều hỗ trợ các bẫy gỡ lỗi, ví dụ kích hoạt khi IP (con trỏ lệnh) bằng với địa chỉ được lưu trong một thanh ghi điểm dừng, tiết kiệm nhu cầu viết lại mã. .
Ben Voigt

Re "Nếu bạn thay đổi các thanh ghi CPU ..." trong đoạn cuối, tôi nghĩ bạn có nghĩa là "Nếu bạn thay đổi bản sao đã lưu của các thanh ghi CUP ..." Sau đó, khi HĐH tiếp tục lại quá trình, dữ liệu đã thay đổi đó sẽ được ghi lại để đăng ký thực tế.
jamesqf

@jamesqf, vâng, thx!
Erik Eidt

@BenVoigt, đồng ý. mặc dù trình gỡ lỗi có thể xử lý số lượng điểm dừng không giới hạn, phần cứng có thể xử lý 0 hoặc một số ít, do đó trình gỡ lỗi phải thực hiện một số thao tác tung hứng.
Erik Eidt

@jamesqf: Mô tả rằng như là một bản sao là một chút sai lệch. Đây là bộ lưu trữ chính thức cho trạng thái luồng trong khi luồng không chạy.
Ben Voigt

5

Nói đúng ra, ít nhất là trong hầu hết các trường hợp điển hình, bản thân gdb không tạm dừng thực thi. Thay vào đó, gdb yêu cầu HĐH và HĐH tạm dừng thực thi.

Điều đó ban đầu có vẻ như là một sự khác biệt mà không có sự khác biệt - nhưng thành thật mà nói, thực sự có một sự khác biệt. Sự khác biệt là ở chỗ: khả năng đó đã được tích hợp sẵn trong HĐH thông thường, bởi vì nó phải có khả năng tạm dừng và bắt đầu lại việc thực thi luồng dù thế nào - khi một luồng không được lên lịch để chạy (ví dụ: nó cần một số tài nguyên mà hiện không có sẵn) hệ điều hành cần tạm dừng nó cho đến khi nó có thể được lên lịch để chạy.

Để làm điều đó, HĐH thường có một khối bộ nhớ dành riêng cho mỗi luồng để lưu trạng thái hiện tại của máy. Khi cần tạm dừng một luồng, trạng thái hiện tại của máy được lưu trong khu vực đó. Khi cần khôi phục một chuỗi, trạng thái của máy được khôi phục từ khu vực đó.

Khi trình gỡ lỗi cần tạm dừng một luồng, hệ điều hành sẽ tạm dừng luồng đó chính xác giống như các lý do khác. Sau đó, để đọc trạng thái của luồng bị tạm dừng, trình gỡ lỗi nhìn vào trạng thái đã lưu của luồng. Nếu bạn sửa đổi trạng thái, trình gỡ lỗi ghi vào trạng thái đã lưu, khi đó sẽ có hiệu lực khi luồng được tiếp tục.

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.