เหตุใด GDB จึงต้องมีความสามารถในการเรียกใช้งานได้ดีรวมถึง core dump


11

ฉันกำลังดีบักโดยใช้ core dumps และโปรดทราบว่า gdb ต้องการให้คุณส่งไฟล์ที่สามารถเรียกทำงานได้รวมถึง core dump ทำไมนี้ หากคอร์ดัมพ์มีหน่วยความจำทั้งหมดที่กระบวนการใช้อยู่จะไม่มีไฟล์ประมวลผลภายในคอร์ดัมพ์หรือไม่ อาจไม่มีการรับประกันว่า exe ทั้งหมดจะถูกโหลดเข้าสู่หน่วยความจำ (โดยปกติไฟล์ปฏิบัติการแต่ละไฟล์จะไม่ใหญ่มากนัก) หรือบางทีการถ่ายโอนข้อมูลหลักอาจไม่มีหน่วยความจำที่เกี่ยวข้องทั้งหมดหลังจากทั้งหมด? สำหรับสัญลักษณ์ (บางทีพวกเขาไม่ได้โหลดเข้าสู่หน่วยความจำตามปกติ)?


1
ปฏิบัติการมีสัญลักษณ์ข้อมูลตามที่ระบุไว้ในเอกสาร gdb และ ...
โทมัสผ้ากันเปื้อน

1
น่าแปลกที่ไม่มีคำตอบ (ยกเว้นที่ฉันเพิ่งเพิ่ม) พูดถึงรูปแบบ
DWARF

คำตอบ:


15

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

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

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

objdump -h a.outดัมพ์ข้อมูลส่วนหัวเท่านั้นคุณจะเห็นส่วนชื่อเช่น .dataหรือ. bssหรือ. text (มีอีกมากมาย) สิ่งเหล่านี้แจ้งเคอร์เนลโหลดเดอร์ซึ่งในส่วนต่าง ๆ ของวัตถุสามารถพบได้และตำแหน่งใดในพื้นที่แอดเดรสของกระบวนการควรโหลดส่วนและในบางส่วน (เช่น. data. text) ควรจะโหลดอะไร (.bss ส่วนไม่มีข้อมูลใด ๆ ในไฟล์ แต่มันหมายถึงจำนวนหน่วยความจำที่จะจองในกระบวนการสำหรับข้อมูลที่ไม่มีการกำหนดค่าเริ่มต้นซึ่งจะเต็มไปด้วยศูนย์)

โครงร่างของไฟล์วัตถุที่ปฏิบัติการได้เป็นไปตามมาตรฐาน ELF

objdump -x a.out - ทิ้งทุกอย่าง

หากวัตถุที่ปฏิบัติการได้ยังคงมีตารางสัญลักษณ์ (มันไม่ได้ถูกปล้น - man stripและคุณใช้-gในการสร้างการดีบักเพื่อgcc สมมติว่าการรวบรวมแหล่ง AC) จากนั้นคุณสามารถตรวจสอบเนื้อหาหลักโดยชื่อสัญลักษณ์เช่นถ้าคุณมีตัวแปร / บัฟเฟอร์ ชื่อinputLineในซอร์สโค้ดของคุณคุณสามารถใช้ชื่อนั้นgdbเพื่อดูเนื้อหา คือgdbจะรู้ว่าออฟเซ็ตจากจุดเริ่มต้นของโปรแกรมของคุณเริ่มต้นส่วนข้อมูลที่inputLineเริ่มและความยาวของตัวแปรนั้น

อ่านเพิ่มเติมarticle1 , ข้อ 2และสำหรับ nitty ทรายปฏิบัติการและการเชื่อมโยงรูปแบบ (ELF) สเปค


อัปเดตหลังจากความคิดเห็น @mirabilos ด้านล่าง

แต่ถ้าใช้ตารางสัญลักษณ์เหมือนใน

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

ผลิต

 0x601060 <buf1>:    0x72617453

จากนั้นไม่ใช้ตารางสัญลักษณ์และตรวจสอบที่อยู่โดยตรง

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

ผลิต

0x601060:   0x72617453

ฉันตรวจสอบหน่วยความจำโดยตรงโดยไม่ใช้ตารางสัญลักษณ์ในคำสั่งที่ 2


ฉันเห็นด้วยเช่นกันว่าคำตอบของ @ user580082 จะเพิ่มคำอธิบายเพิ่มเติมและจะโหวตให้


6
ไม่เคยได้ยินเรื่อง "ส่วนสแต็กพื้นฐาน" .bssเป็น (อดีต) "บล็อกที่ตั้งขึ้นโดยสัญลักษณ์" และปฏิบัติจริง "ข้อมูล unitialized" ในขณะที่.dataถูกและ "ข้อมูลเริ่มต้น" ข้อความ (ไม่ .code) จะใช้ในการเก็บรหัสเครื่อง ไม่มีส่วนสแต็กในไบนารีเนื่องจากสแต็กถูกสร้างในขณะใช้งาน
jlliagre

“ ถ้าคุณรู้ว่าทุกอย่างอยู่ที่ไหนคุณก็สามารถใช้สิ่งนั้นได้” ไม่เป็นความจริงเพราะทุกอย่างในโปรแกรมนั้นไม่จำเป็นต้องรวมอยู่ในรอยเท้า
mirabilos

1
@jlliagre คุณถูกต้องฉันเรียกผิด. text. รหัส (เนื่องจากฉันคิดว่าคำอธิบายขณะเขียนคำตอบ) - อัปเดต ฉันคิดผิดพลาดว่าชื่อ bss ไม่ถูกต้องและได้อัปเดตคำตอบของฉันแล้ว แต่หลีกเลี่ยง * Block Started โดย Symbol เนื่องจากฉันไม่คิดว่ามันเพิ่มสมกับจริง ๆ และได้อธิบายว่ามันถูกใช้เป็นข้อมูลที่ยังไม่เริ่มต้นซึ่งเป็น ความเข้าใจร่วมกัน ขอบคุณ - ฉันชื่นชมความคิดเห็นของคุณเพื่อแก้ไขการโพสต์นี้
X Tian

4

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

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

ในกระบวนการหลักของ Linux สามารถรับข้อมูลเพิ่มเติมเกี่ยวกับลูก ๆ ของพวกเขาได้โดยเฉพาะอย่างยิ่งความสามารถในการ ptrace พวกเขาซึ่งอนุญาตให้ดีบักเกอร์เข้าถึงข้อมูลระดับต่ำของกระบวนการเช่นอ่าน / เขียนหน่วยความจำลงทะเบียนเปลี่ยนการแมปสัญญาณหยุดการทำงานเป็นต้น

คุณจะเข้าใจถึงความต้องการของไฟล์สั่งการที่สามารถเรียกใช้งานได้ของไฟล์หลักอีกครั้งเมื่อคุณอ่านการทำงานของดีบักเกอร์


1

(นอกเหนือจากคำตอบที่ดีอื่น ๆ )

บนระบบ Linux (และ Unix-like) ที่ทันสมัย, ข้อมูลการดีบั๊ก (รวมถึง meta-data เกี่ยวกับประเภทของสัญลักษณ์, ตำแหน่งของซอร์สโค้ด, ชนิดของตัวแปร, ฯลฯ ... ) อยู่ในรูปแบบDWARFและอยู่ในปฏิบัติการELF ( หรือ ELF shared library) เมื่อคอมไพล์ด้วย-gตัวเลือกบางตัว ผมขอแนะนำให้รวบรวมโปรแกรมที่จะบั๊กด้วย-g3 -O0และบางที-fno-inlineถ้าใช้ล่าสุดGCC ; อย่างไรก็ตามด้วย GCC คุณสามารถคอมไพล์ด้วยทั้งการเพิ่มประสิทธิภาพและข้อมูลการดีบักเช่นด้วย-O2 -g1แม้ว่าข้อมูลการดีบักอาจเป็นบิต "คลุมเครือ" (นี่อาจช่วยในการจับHeisenbugs ที่ซุกซนเล็กน้อย )

มันค่อนข้างสมเหตุสมผลที่จะหลีกเลี่ยงการใส่ข้อมูลนั้นลงในไฟล์coreเพราะคุณอาจมีไฟล์ core ที่แตกต่างกัน (ลองนึกภาพซอฟต์แวร์ที่ใช้กันอย่างแพร่หลายกับผู้ใช้หลายคนที่ทำรายงานข้อผิดพลาดส่วนใหญ่ที่มีการcoreถ่ายโอนข้อมูล) นอกจากนี้ไฟล์core (5)จะถูกดัมพ์โดยเคอร์เนลซึ่งไม่ควรสนใจเกี่ยวกับการมีอยู่ของส่วน DWARF ในexecutables elf (5) (เนื่องจากส่วนเหล่านี้ไม่ได้ถูกแมปเข้าไปในพื้นที่ที่อยู่เสมือนของกระบวนการ faulting ที่ทิ้ง core ในสัญญาณบางตัว ( 7) ) แม้มีความเป็นไปได้ที่จะมีข้อมูลการดีบักถูกวางในไฟล์แยกต่างหาก (นอกการปฏิบัติการ)

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

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