GDB หยุดการดำเนินการชั่วคราวอย่างไร


16

อย่างที่คุณอาจทราบเราสามารถใช้ GDB และกำหนดจุดพักบนรหัสของเราเพื่อหยุดการประมวลผลชั่วคราวสำหรับการดีบัก

คำถามของฉันคือ GDB หยุดกระบวนการอย่างไรและให้คุณดูเนื้อหาของการลงทะเบียนโดยใช้i rตัวอย่างเช่น การลงทะเบียนเหล่านั้นถูกใช้โดยกระบวนการ OS อื่น ๆ อย่างต่อเนื่องหรือ พวกเขาจะไม่ถูกเขียนทับได้อย่างไร?

เป็นเพียงภาพรวมของเนื้อหาและไม่ใช่ข้อมูลจริง


2
ทำไมรีจิสเตอร์ทั้งหมดถึงไม่ถูกเขียนทับเมื่อระบบปฏิบัติการตัดสินใจที่จะหยุดโปรแกรมชั่วคราวชั่วขณะหนึ่งแล้วรันแอปอื่น
253751

CppCon 2018: แบรนด์ Simon "วิธีแก้ปัญหา C ++ Debuggers" youtube.com/watch?v=0DDrseUomfU
Robert Andrzejuk

คำตอบ:


24

มันแตกต่างกันเล็กน้อยกับสถาปัตยกรรม แต่จุดสำคัญที่ใช้กันอย่างแพร่หลายเกือบทั้งหมด:

  • การบริการขัดจังหวะทำให้สถานะของ CPU (รวมถึงการลงทะเบียน) ถูกบันทึกลงในหน่วยความจำก่อนเรียกใช้ ISR และเรียกคืนเมื่อ ISR ออก

  • หากประจำบริการขัดจังหวะ swaps เนื้อหาของตำแหน่งหน่วยความจำที่ลงทะเบียนผู้ที่จะถูกบันทึกไว้ก็สามารถดำเนินการเปลี่ยนบริบท ทุกเธรดมีขอบเขตหน่วยความจำที่บันทึกการลงทะเบียนไว้เมื่อเธรดไม่ทำงาน

  • การสลับบริบทถูกควบคุมโดยตัวกำหนดตารางเวลาเธรดซึ่งคำนึงถึงว่าเธรดกำลังรอ I / O การซิงโครไนซ์ความสำคัญของมันคือการส่งสัญญาณ ฯลฯ มักจะมีการนับจำนวน suspend ซึ่งเป็นปัจจัยสำคัญ

  • ตัวดีบักสามารถเพิ่มจำนวนการหยุดชั่วคราวซึ่งรับประกันว่าเธรดจะไม่สามารถรันได้ จากนั้นสามารถตรวจสอบ (และเปลี่ยนแปลง) สำเนาของการลงทะเบียนที่บันทึกไว้ของเธรด


14

นอกจากข้อมูลที่ยอดเยี่ยมโดย @BenVoigt อนุญาตให้ฉันทำการเพิ่มเติม:

จุดพักถูกตั้งค่าโดยดีบักเกอร์โดยแทนที่ค่ารหัสเครื่อง (คำสั่งหรือส่วนหนึ่งของคำสั่ง) ในกระบวนการที่กำลังดีบั๊กด้วยคำสั่งแทร็บเฉพาะที่ตำแหน่งในรหัสที่สอดคล้องกับบรรทัด (ซอร์ส) ที่ต้องการเพื่อแยก คำสั่ง trap นี้มีไว้สำหรับใช้เป็นจุดพัก - ดีบักรู้เรื่องนี้และระบบปฏิบัติการก็เช่นกัน

เมื่อกระบวนการ / เธรดที่กำลังดีบั๊กกระทบกับคำสั่งแทร็บซึ่งเป็นสาเหตุให้กระบวนการ @Ben กำลังอธิบายซึ่งรวมถึงครึ่งหนึ่งของการแลกเปลี่ยนบริบทที่ระงับเธรดที่กำลังทำงานอยู่ในปัจจุบัน (ซึ่งรวมถึงการบันทึกสถานะ CPU ไปยังหน่วยความจำ) เนื่องจากกับดักนี้เป็นกับดักเบรกพอยต์ระบบปฏิบัติการจะเก็บกระบวนการที่ถูกดีบั๊กไว้ชั่วคราวโดยใช้กลไก @Ben อธิบายและแจ้งให้ทราบและในที่สุดก็จะกลับมาทำงานในการดีบัก

ดีบักเกอร์ใช้การเรียกของระบบจากนั้นเพื่อเข้าถึงสถานะที่บันทึกไว้ของกระบวนการ / เธรดที่ถูกหยุดชั่วคราวที่กำลังดีบั๊ก

ในการดำเนินการ (ทำต่อ) บรรทัดของรหัสที่แตก (ซึ่งตอนนี้มีคำสั่งแทร็บเฉพาะ) ดีบักเกอร์จะเรียกคืนค่ารหัสเครื่องดั้งเดิมที่เขียนทับด้วยคำสั่งแทร็บเบรกพอยต์อาจตั้งกับดักอื่นได้ หรือผู้ใช้สร้างเบรกพอยต์ใหม่) และทำเครื่องหมายกระบวนการ / เธรดว่าสามารถรันได้บางทีอาจใช้กลไกตามที่ @Ben อธิบาย

รายละเอียดที่แท้จริงอาจมีความซับซ้อนมากขึ้นในการทำให้เบรกพอยต์ที่รันเป็นเวลานานหมายถึงการทำอะไรบางอย่างเช่นการสลับกับดักเบรกพอยต์สำหรับรหัสจริงเพื่อให้บรรทัดนั้นสามารถทำงานได้

การลงทะเบียนเหล่านั้นถูกใช้โดยกระบวนการ OS อื่น ๆ อย่างต่อเนื่องใช่หรือไม่ พวกเขาจะไม่ถูกเขียนทับได้อย่างไร?

ดังที่ @Ben อธิบายไว้การใช้คุณสมบัติการหยุดชั่วคราว / เรียกคืนเธรดที่มีอยู่แล้ว (การสลับบริบท / การสลับการทำงานหลายภารกิจ ) ที่อนุญาตให้ตัวประมวลผลร่วมกันโดยใช้หลายกระบวนการ / เธรดโดยใช้การแบ่งเวลา

เป็นเพียงภาพรวมของเนื้อหาและไม่ใช่ข้อมูลจริง

มันเป็นทั้ง ตั้งแต่ด้ายที่ตีเบรกพอยต์ถูกระงับมันเป็นภาพรวมของข้อมูลสด (ลงทะเบียน CPU ฯลฯ .. ) ในช่วงเวลาของการระงับและต้นแบบเผด็จการของค่า CPU ลงทะเบียนเพื่อคืนค่าลงในหน่วยประมวลผลที่ควรจะเป็นด้ายกลับมา . หากคุณใช้ส่วนต่อประสานผู้ใช้ของดีบั๊กเกอร์ในการอ่านและ / หรือเปลี่ยนการลงทะเบียน CPU (ของกระบวนการที่กำลังดีบั๊ก) มันจะอ่านและ / หรือเปลี่ยนสแนปชอต / ต้นแบบนี้โดยใช้การเรียกระบบ


1
สถาปัตยกรรมโปรเซสเซอร์ส่วนใหญ่รองรับการตรวจแก้จุดบกพร่องตัวอย่างเช่นทริกเกอร์เมื่อ IP (ตัวชี้คำสั่ง) เท่ากับที่อยู่ที่เก็บไว้ในเบรกพอยต์การลงทะเบียนประหยัดความจำเป็นในการเขียนรหัสใหม่ (โดยการจับคู่การลงทะเบียนนอกเหนือจาก IP คุณจะได้รับจุดพักข้อมูลและการดักจับหลังคำสั่งทุกครั้งคุณสามารถทำขั้นตอนเดียว) สิ่งที่คุณอธิบายไว้อาจเป็นไปได้แน่นอนตราบใดที่รหัสไม่ได้อยู่ในหน่วยความจำแบบอ่านอย่างเดียว
Ben Voigt

เรื่อง "ถ้าคุณแก้ไขการลงทะเบียน CPU ... " ในย่อหน้าสุดท้ายฉันคิดว่าคุณหมายถึง "ถ้าคุณแก้ไขสำเนาที่บันทึกของการลงทะเบียน CUP ... " จากนั้นเมื่อระบบปฏิบัติการดำเนินการต่อกระบวนการข้อมูลที่เปลี่ยนแปลงจะถูกเขียนกลับ เพื่อลงทะเบียนจริง
jamesqf

@jamesqf ใช่ขอบคุณ!
Erik Eidt

@BenVoigt เห็นด้วย แม้ว่าในขณะที่ดีบั๊กเกอร์สามารถจัดการกับเบรกพอยต์ได้ไม่ จำกัด จำนวนฮาร์ดแวร์สามารถจัดการกับศูนย์หรือไม่กี่ดังนั้นดีบักเกอร์จะต้องเล่นกล
Erik Eidt

@jamesqf: การอธิบายว่าการทำสำเนาเป็นการทำให้เข้าใจผิดเล็กน้อย เป็นที่เก็บข้อมูลอย่างเป็นทางการสำหรับสถานะเธรดในขณะที่เธรดไม่ทำงาน
Ben Voigt

5

อย่างน้อยการพูดอย่างเคร่งครัดในกรณีทั่วไปส่วนใหญ่ gdb นั้นไม่ได้หยุดการทำงานชั่วคราว ค่อนข้าง gdb ถามระบบปฏิบัติการและระบบปฏิบัติการหยุดการทำงานชั่วคราว

ในตอนแรกอาจดูเหมือนความแตกต่างที่ไม่มีความแตกต่าง - แต่จริงๆแล้วมันมีความแตกต่าง ความแตกต่างคือ: ความสามารถนั้นได้ถูกสร้างไว้ในระบบปฏิบัติการทั่วไปแล้วเพราะมันจะต้องสามารถหยุดและเริ่มการทำงานของเธรดได้อีกครั้ง - เมื่อเธรดไม่ได้ถูกกำหนดเวลาให้ทำงาน (เช่นต้องการทรัพยากรบางอย่างที่ ไม่สามารถใช้งานได้ในปัจจุบัน) ระบบปฏิบัติการต้องหยุดชั่วคราวจนกว่าจะสามารถกำหนดตารางเวลาให้ทำงานได้

ในการทำเช่นนั้นโดยทั่วไประบบปฏิบัติการจะมีบล็อกหน่วยความจำที่ตั้งค่าไว้สำหรับแต่ละเธรดเพื่อบันทึกสถานะปัจจุบันของเครื่อง เมื่อต้องการหยุดเธรดชั่วคราวสถานะปัจจุบันของเครื่องจะถูกบันทึกในพื้นที่นั้น เมื่อต้องการเริ่มเธรดต่อสถานะของเครื่องจะถูกกู้คืนจากพื้นที่นั้น

เมื่อดีบักเกอร์ต้องการหยุดเธรดชั่วคราวจะมีการหยุดชั่วคราวของระบบปฏิบัติการที่เธรดเหมือนกับวิธีการอื่น ๆ จากนั้นเมื่อต้องการอ่านสถานะของเธรดที่หยุดชั่วคราวดีบักเกอร์จะดูสถานะที่บันทึกไว้ของเธรด ถ้าคุณปรับเปลี่ยนสถานะดีบักเกอร์เขียนไปยังสถานะที่บันทึกไว้เมื่อนั้นจะมีผลเมื่อเธรดดำเนินต่อ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.