รับ GDB เพื่อบันทึกรายการเบรกพอยต์


129

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

ไฟล์. gdbinit มีปัญหาเหมือนกับ --command ข้อมูลแบ่งคำสั่งไม่ได้แสดงรายการคำสั่ง แต่เป็นโต๊ะสำหรับมนุษย์บริโภค

ในการอธิบายอย่างละเอียดนี่คือตัวอย่างจากตัวแบ่งข้อมูล :

(gdb) ตัวแบ่งข้อมูล
Num Type Disp Enb Address คืออะไร
1 เบรกพอยต์ให้ y 0x08048517 <foo :: bar (โมฆะ) +7>

คำตอบ:


204

ตั้งแต่ GDB 7.2 (2011-08-23) คุณสามารถใช้คำสั่งบันทึกเบรกพอยต์ได้แล้ว

save breakpoints <filename>
  Save all current breakpoint definitions to a file suitable for use
  in a later debugging session.  To read the saved breakpoint
  definitions, use the `source' command.

ใช้source <filename>เพื่อกู้คืนเบรกพอยต์ที่บันทึกไว้จากไฟล์


2
แล้วถ้าพวกเขามาจากโหลด lib ที่ใช้ร่วมกัน? มันตอบ N โดยค่าเริ่มต้นดูเหมือนว่า ...Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
bjackfly


โปรดทราบว่าเมื่อคุณมีเงื่อนไขเบรกพอยต์ซึ่งไม่สามารถแก้ไขได้เมื่อเริ่มต้น ( break g_log if log_level==G_LOG_LEVEL_CRITICAL) อย่างน้อย gdb 7.8.1 จะหยุดการแยกวิเคราะห์คำสั่งเพิ่มเติม หากคุณมีคำสั่งเพิ่มเติมที่ควรดำเนินการสำหรับเบรกพอยต์นั้นให้วางcommandsบรรทัดไว้หน้าconditionบรรทัด
Lekensteyn

@ แอนดรีฉันย้อนการแก้ไขของคุณกลับไปเป็น blockquote เดิมของฉันเนื่องจากข้อความเป็นคำพูดคำต่อคำจากเอกสาร ... ฉันจะเห็นด้วยกับการแก้ไขของคุณหากเป็นคำพูดของฉันเอง
aculich

@aculich: ฉันเข้าใจ ฉันอยากจะแนะนำให้ใช้สไตล์การเสนอราคาแทนสไตล์โค้ดไม่ว่าในกรณีใด ๆ
Andry

26

คำตอบนี้ล้าสมัย GDB รองรับการบันทึกโดยตรงแล้ว ดูคำตอบนี้

คุณสามารถใช้การบันทึก:

(gdb) b main
Breakpoint 1 at 0x8049329
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>
(gdb) set logging file breaks.txt
(gdb) set logging on
Copying output to breaks.txt.
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>
(gdb) q

ตอนนี้ไฟล์ breaks.txt ประกอบด้วย:

Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>

การเขียนสคริปต์ AWK ที่แปลงสิ่งนั้นให้อยู่ในรูปแบบที่มีประโยชน์สำหรับไฟล์.gdbinitหรือ--commandไฟล์นั้นเป็นเรื่องง่าย หรือคุณอาจทำให้สคริปต์แยกออกจาก--eval-commandบรรทัดคำสั่ง GDB ...

การเพิ่มมาโครขนาดเล็กนี้ลงใน. gdbinitจะช่วยคุณได้:

# Call with dump_breaks file.txt
define dump_breaks
    set logging file $arg0
    set logging redirect on
    set logging on
    info breakpoints
    set logging off
    set logging redirect off
end

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

1
ฉันไม่คิดว่าการตัดแล้ววางจะง่ายไปกว่าการเขียนสคริปต์เพียงครั้งเดียวแล้วใช้ทุกครั้งอีกครั้ง :) นั่นคือเหตุผลที่คุณถามคำถามนี้ตั้งแต่แรกฉันคิดว่า :)
โจฮันเนส Schaub - litb

อืมฉันหมายถึงใช้การตัดแล้ววางแทนวิธีการบันทึก การเขียนสคริปต์เป็นเรื่องที่แน่นอนแล้ว
casualcoder

ว้าว! gdb ล้มเหลว! ฉันใช้มันทุกวันและชอบคุณสมบัติมากมายของมัน แต่การขาดเป็นเพียงใบ้ธรรมดา
deft_code

4
คำตอบนี้มีอายุเกิน 2 ปีแล้วดังนั้นจึงอาจล้าสมัยหากคุณใช้ gdb เวอร์ชันใหม่กว่า ใน gdb 7.2 คุณสามารถใช้save breakpointsคำสั่งได้แล้ว
aculich

11

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


1
สิ่งนี้ใช้งานไม่ได้จริงฉันได้รับ "คำเตือน: save-tracepoints: ไม่มี tracepoints ให้บันทึก" แม้ว่าจะมีการตั้งจุดพักการใช้ gdb 6.8
casualcoder

สิ่งนี้ใช้ได้กับฉัน GDB ต้องการการมีอยู่ของ. gdbinit ส่วนกลางใน $ HOME / .gdbinit ของคุณที่มีเนื้อหา 'add-auto-load-safe-path /home/johnny/src/.gdbinit' ดังนั้น src / โฟลเดอร์จึงมี. gdbinit แยกต่างหาก
truthadjustr

9

ส่วนขยายไปยังส่วนขยายของอานนท์เพื่อคำตอบที่โยฮันเน :

.gdbinit:

define bsave
    shell rm -f brestore.txt
    set logging file brestore.txt
    set logging on
    info break
    set logging off
    # Reformat on-the-fly to a valid GDB command file
    shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdb
end
document bsave
  store actual breakpoints
end

define brestore
  source brestore.gdb
end
document brestore
  restore breakpoints saved by bsave
end

กับคุณแล้วคุณสามารถเรียกคืนจุดพักที่บันทึกไว้ด้วยbrestorebsave


นี่คือ regex ที่ดีกว่า: perl -ne "print \" break \ $ 1 \ n \ "if /at\s(.*:\d+)/" brestore.txt
George Godik

6

ส่วนขยายของคำตอบจาก Johannes : คุณสามารถฟอร์แมตเอาต์พุตใหม่info breakเป็นไฟล์คำสั่ง GDB ที่ถูกต้องโดยอัตโนมัติ:

.gdbinit:

define bsave
   shell rm -f brestore.txt
   set logging file brestore.txt
   set logging on
   info break
   set logging off
   # Reformat on-the-fly to a valid gdb command file
   shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdb
end
document bsave
  store actual breakpoints
end

หลังจากนั้นคุณมีไฟล์คำสั่งที่ถูกต้องในbrestore.gdb.

สิ่งนี้ใช้ได้ผลสำหรับฉันเมื่อแอปพลิเคชันถูกรวบรวมด้วย-gไฟล์.

ฉันยังทดสอบกับ GDB v6.8 บนUbuntu 9.10 (Karmic Koala) ได้สำเร็จ


1
ขอบคุณสำหรับตัวอย่างนี้! ใช้งานได้ดี ประสบความสำเร็จในการทดสอบกับ GNU gdb 6.3.50-20050815 (Apple เวอร์ชัน gdb-966) ใน CarbonEmacs GNU Emacs 22.3.1 (i386-apple-darwin9.6.0, Carbon Version 1.6.0) บน Mac OS 10.5.8
pestophagous


3

ใส่สิ่งต่อไปนี้ใน~ / .gdbinitเพื่อกำหนดbsaveและbrestoreเป็นคำสั่ง GDB เพื่อบันทึกและกู้คืนเบรกพอยต์

define bsave
    save breakpoints ~/.breakpoints
end

define brestore
   source ~/.breakpoints
end

1

คำเตือน: โปรโตคอลเอาต์พุตปัจจุบันไม่รองรับการเปลี่ยนเส้นทาง

ฉันยังได้รับข้อผิดพลาด / คำเตือนนี้ใน GDB เมื่อพยายามเปิดใช้งานการบันทึกในโหมดTUI อย่างไรก็ตามดูเหมือนว่าการบันทึกจะใช้งานได้เมื่ออยู่ในโหมด "non-TUI" ดังนั้นฉันจึงออกจากโหมด TUI ทุกครั้งที่ฉันต้องการบันทึกบางสิ่ง (สลับไปมาในโหมด TUI ด้วยCtrl+X , Ctrl+A )

นี่คือวิธีการทำงาน:

  1. เริ่ม GDB (ในโหมดปกติ)
  2. เปิดใช้งานการบันทึก: set logging on- ตอนนี้ไม่ควรบ่น
  3. สลับไปมาเป็นโหมด TUI และทำสิ่งต่างๆของ GDB
  4. เมื่อใดก็ตามที่ฉันต้องการบันทึกบางสิ่งบางอย่าง (เช่นการถ่ายโอนข้อมูลย้อนกลับขนาดใหญ่) - สลับเป็นโหมดปกติ

อ้อและถ้าคุณชอบใช้ "หน้าจอ" (เหมือนที่ฉันทำ) มันจะยุ่งหน่อยเพราะมันใช้ปุ่มลัดเดียวกัน
Magnux

1

ฉันพบว่าส่วนเพิ่มเติมต่อไปนี้ของคำตอบก่อนหน้านี้มีประโยชน์ในการบันทึก / โหลดเบรกพอยต์ลงในไฟล์เฉพาะ

  • บันทึกเบรกพอยต์: bsave {filename}
  • โหลดเบรกพอยต์: bload {filename}

ในคำตอบก่อนหน้านี้ให้เพิ่มรหัสต่อไปนี้ในไฟล์ ~ / .gdbinit

# Save breakpoints to a file
define bsave
    if $argc != 1
        help bsave
    else
    save breakpoints $arg0
    end
end
document bsave
Saves all current defined breakpoints to the defined file in the PWD
Usage: bsave <filename>
end

# Loads breakpoints from a file
define bload
    if $argc != 1
        help bload
    else
        source $arg0
    end
end
document bload
Loads all breakpoints from the defined file in the PWD
Usage: bload <filename>
end

0

ปัญหาคือการตั้งค่าเบรกพอยต์มีความอ่อนไหวตามบริบท จะเกิดอะไรขึ้นถ้าคุณมีฟังก์ชันคงที่สองชื่อfoo ?

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


0

ความคิดอื่น ๆ ? ฉันได้รับ

warning: Current output protocol does not support redirection

หลังจาก

set logging on

แก้ไข:

ฉันรู้ว่าคำถามนั้นคือ "วิธีบันทึกรายการเบรกพอยต์" แต่ฉันเพิ่งค้นพบว่าด้วย GDB เราสามารถตั้งค่าเบรกพอยต์ที่ "บันทึกไว้ในไฟล์" ได้โดย

gdb> source breakpoints.txt

breakpoints.txtไฟล์แบบนี้อยู่ที่ไหน:

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