ดีบักเกอร์ทำงานอย่างไร


170

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


5
บทความของ Eli ได้ย้ายไปที่eli.thegreenplace.net/2011/01/23/how-debuggers-work-part-1
Oktalist

@Oktalist บทความนี้น่าสนใจ แต่พูดถึงเฉพาะเกี่ยวกับนามธรรมระดับ API สำหรับการดีบักบน Linux ฉันเดาว่า OP อยากรู้เพิ่มเติมเกี่ยวกับกระโปรงหน้ารถ
smwikipedia

คำตอบ:


96

รายละเอียดของการทำงานของดีบักเกอร์จะขึ้นอยู่กับว่าคุณกำลังดีบักอะไรและระบบปฏิบัติการคืออะไร สำหรับการแก้จุดบกพร่องพื้นเมืองใน Windows คุณสามารถหารายละเอียดบางอย่างใน MSDN: Win32 API

ผู้ใช้บอกดีบักเกอร์ว่ากระบวนการใดที่จะแนบไม่ว่าจะด้วยชื่อหรือตาม ID กระบวนการ หากเป็นชื่อตัวดีบักจะค้นหา ID กระบวนการและเริ่มต้นเซสชันการดีบักผ่านการเรียกของระบบ ภายใต้ Windows นี้จะDebugActiveProcess

เมื่อเชื่อมต่อแล้วตัวดีบักจะเข้าสู่ลูปเหตุการณ์คล้ายกับ UI ใด ๆ แต่แทนที่จะเป็นเหตุการณ์ที่มาจากระบบหน้าต่างระบบปฏิบัติการจะสร้างเหตุการณ์ตามสิ่งที่เกิดขึ้นในกระบวนการที่กำลังดีบั๊กตัวอย่างเช่นข้อยกเว้นที่เกิดขึ้น ดูWaitForDebugEvent

ดีบักเกอร์สามารถอ่านและเขียนหน่วยความจำเสมือนของกระบวนการเป้าหมายและปรับค่าการลงทะเบียนผ่าน API ที่จัดทำโดยระบบปฏิบัติการ ดูรายการฟังก์ชั่นการแก้ไขข้อบกพร่องสำหรับ Windows

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

หากคุณกำลังดีบักสภาพแวดล้อมที่มีการจัดการ (.NET, Java, ฯลฯ ) โดยทั่วไปกระบวนการจะมีลักษณะคล้ายกัน แต่รายละเอียดจะแตกต่างกันเนื่องจากสภาพแวดล้อมของเครื่องเสมือนมี API การดีบักแทนที่จะเป็นระบบปฏิบัติการพื้นฐาน


5
คำถามนี้อาจฟังดูงี่เง่า แต่ระบบปฏิบัติการติดตามอย่างไรหากมีที่อยู่เฉพาะภายในโปรแกรมถึง เช่น Breackpoint ตั้งอยู่ที่ที่อยู่ 0x7710cafe เมื่อตัวชี้คำแนะนำเปลี่ยนระบบปฏิบัติการ (หรือ CPU) จะต้องเปรียบเทียบตัวชี้คำแนะนำกับที่อยู่จุดพักทั้งหมดหรือฉันเข้าใจผิด? มันทำงานอย่างไร ..
displayname

3
@StefanFalk ฉันเขียนคำตอบที่กล่าวถึงรายละเอียดระดับล่าง (บน x86)
Jonathon Reinhart

คุณช่วยอธิบายว่าชื่อตัวแปรจับคู่กับที่อยู่ได้อย่างไร? แอปพลิเคชันใช้ที่อยู่หน่วยความจำเดียวกันสำหรับตัวแปรทุกครั้งที่เรียกใช้หรือไม่ ฉันสันนิษฐานเสมอว่าพบเพียงแมปจากหน่วยความจำที่มีอยู่ แต่ไม่เคยคิดเลยว่าไบต์จะแมปไปยังจุดเดียวกันโดยตรงในพื้นที่หน่วยความจำของแอปหรือไม่ ดูเหมือนว่าจะเป็นปัญหาด้านความปลอดภัยที่สำคัญ
James Joshua Street

@JamesJoshuaStreet ฉันคิดว่านั่นเป็นรายละเอียดเฉพาะสำหรับผู้ดีบั๊ก
moonman239

คำตอบนี้เผยให้เห็นบางสิ่งบางอย่าง แต่ฉันคิดว่า op มีความสนใจในรายละเอียดในระดับต่ำมากกว่าบาง abstractions API
smwikipedia

63

ตามที่ฉันเข้าใจ

สำหรับจุดพักซอฟต์แวร์บน x86 ตัวดีบักจะแทนที่ไบต์แรกของคำสั่งด้วยCC( int3) สิ่งนี้ทำกับWriteProcessMemoryWindows เมื่อ CPU เข้าสู่คำสั่งนั้นและดำเนินการint3สิ่งนี้จะทำให้ CPU สร้างข้อยกเว้นการดีบัก ระบบปฏิบัติการได้รับการขัดจังหวะนี้ตระหนักถึงกระบวนการกำลังดีบั๊กและแจ้งให้ทราบถึงกระบวนการดีบักเกอร์ที่จุดพักถูกตี

หลังจากจุดหยุดถูกโจมตีและกระบวนการหยุดทำงานดีบักเกอร์จะค้นหาในรายการจุดพักและแทนที่CCด้วยไบต์ที่มีอยู่เดิม ดีบักเกอร์ตั้งค่าTFสถานะการดักจับในEFLAGS(โดยแก้ไขCONTEXT) และดำเนินการกระบวนการต่อ กับดักธงทำให้ CPU สร้างข้อยกเว้นขั้นตอนเดียวโดยอัตโนมัติ ( INT 1) ในคำสั่งต่อไป

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

ฉันไม่แน่ใจว่านี่เป็นวิธีการที่ debuggers ใช้จริงหรือไม่ แต่ฉันเขียนโปรแกรม Win32 ที่จัดการเพื่อดีบักตัวเองโดยใช้กลไกนี้ ไร้ประโยชน์อย่างสมบูรณ์ แต่การศึกษา


25

ใน Linux การดีบักกระบวนการเริ่มต้นด้วยการเรียกระบบ ptrace (2) บทความนี้มีบทช่วยสอนที่ยอดเยี่ยมเกี่ยวกับวิธีใช้ptraceเพื่อสร้างโครงสร้างการดีบักอย่างง่าย


1
สิ่งที่(2)บอกเรามากกว่าหรือน้อยกว่า "ptrace คือการเรียกระบบ" หรือไม่?
Lazer

5
@ eSKay ไม่จริง นี่(2)คือหมายเลขส่วนคู่มือ ดูen.wikipedia.org/wiki/Man_page#Manual_sectionsสำหรับคำอธิบายของส่วนที่ใช้
Adam Rosenfield

2
@ AdamRosenfield ยกเว้นความจริงที่ว่าส่วนที่ 2 นั้นเป็น "การโทรผ่านระบบ" โดยเฉพาะ ทางอ้อมใช่มันบอกเราว่าptraceเป็นการเรียกของระบบ
Jonathon Reinhart

1
ที่จริงแล้วสิ่งที่(2)บอกเราว่าเราสามารถพิมพ์man 2 ptraceและรับ manpage ที่ถูกต้อง - ไม่สำคัญที่นี่เพราะไม่มีสิ่งอื่นใดที่ptraceทำให้เข้าใจผิด แต่เพื่อเปรียบเทียบman printfกับman 3 printfLinux
บาง

9

หากคุณใช้ระบบปฏิบัติการ Windows ทรัพยากรที่ยอดเยี่ยมสำหรับสิ่งนี้คือ "การดีบักแอปพลิเคชันสำหรับ Microsoft .NET และ Microsoft Windows" โดย John Robbins:

(หรือแม้แต่รุ่นที่เก่ากว่า: "แอปพลิเคชันดีบั๊ก" )

หนังสือเล่มนี้มีบทหนึ่งเกี่ยวกับวิธีการทำงานของดีบักเกอร์ที่มีรหัสสำหรับการดีบักเกอร์แบบง่าย ๆ แต่ทำงานอยู่

เนื่องจากฉันไม่คุ้นเคยกับรายละเอียดของการดีบัก Unix / Linux สิ่งนี้อาจไม่สามารถใช้กับระบบปฏิบัติการอื่นได้เลย แต่ฉันเดาว่านี่เป็นการแนะนำให้รู้จักกับแนวคิดที่ซับซ้อนมาก - หากไม่ใช่รายละเอียดและ API - ควร "พอร์ต" กับระบบปฏิบัติการส่วนใหญ่


3

อีกแหล่งข้อมูลที่มีค่าที่จะเข้าใจการแก้ไขข้อบกพร่องคือคู่มือ Intel CPU (คู่มือผู้พัฒนาซอฟต์แวร์สถาปัตยกรรมIntel® 64 และ IA-32) ในเล่ม 3A บทที่ 16 แนะนำการสนับสนุนการดีบักของฮาร์ดแวร์เช่นข้อยกเว้นพิเศษและการลงทะเบียนการดีบักฮาร์ดแวร์ ต่อไปนี้มาจากบทที่:

T (กับดัก) แฟล็ก TSS - สร้างข้อยกเว้นการดีบัก (#DB) เมื่อมีการพยายามเปลี่ยนเป็นงานที่มีการตั้งค่าสถานะ T ใน TSS

ฉันไม่แน่ใจว่า Window หรือ Linux ใช้แฟล็กนี้หรือไม่ แต่มันน่าสนใจมากที่จะอ่านบทนั้น

หวังว่านี่จะช่วยใครซักคน


2

ฉันคิดว่ามีสองคำถามหลักที่จะตอบที่นี่:

1. ดีบักเกอร์รู้ได้อย่างไรว่ามีข้อยกเว้นเกิดขึ้น

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

ป้อนคำอธิบายรูปภาพที่นี่


2. ดีบักเกอร์รู้วิธีหยุดเบรกพอยต์ได้อย่างไร

ประยุกต์คำตอบคือเมื่อคุณใส่แบ่งจุดลงในโปรแกรมดีบักแทนที่รหัสของคุณที่จุดที่มีการเรียนการสอน int3 ซึ่งเป็นผู้มีการขัดจังหวะซอฟแวร์ โปรแกรมจะหยุดทำงานชั่วคราวและดีบักเกอร์จะถูกเรียกใช้


1

ความเข้าใจของฉันคือเมื่อคุณรวบรวมแอปพลิเคชันหรือไฟล์ DLL สิ่งใดก็ตามที่คอมไพล์มีสัญลักษณ์ที่แสดงถึงฟังก์ชั่นและตัวแปร

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


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