วิธีการส่งผ่านข้อโต้แย้งและเปลี่ยนเส้นทาง stdin จากไฟล์ไปยังโปรแกรมทำงานใน gdb?


210

ฉันมักจะเรียกใช้โปรแกรมเป็น:

./a.out arg1 arg2 <file

ฉันต้องการดีบักโดยใช้ gdb

ฉันตระหนักถึงการset argsทำงาน แต่ใช้งานได้จากพรอมต์ gdb เท่านั้น

คำตอบ:


136

ส่งผ่านอาร์กิวเมนต์ไปยังrunคำสั่งจากภายใน gdb

$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t

3
rสั้นrunและคุณสามารถทำตามได้ทุกข้อ เช่นเดียวกับในคำถามนี้มันจะเป็น: r arg1 arg2 <fileหรืออาจเป็นrun arg1 arg2 <file
phyatt

สำหรับฉันมันไม่ทำงาน แล้วฉันพยายาม$ gdb ./a.outแล้ว(gdb) r < t arg1 arg2ที่ทำงานที่ดีสำหรับฉัน ในกรณีของฉันa.out = nft arg1 = import arg2 = json และt = file containing json rules
mystictot

410

คุณสามารถทำได้:

gdb --args path/to/executable -every -arg you can=think < of

ความมหัศจรรย์ที่เกิด--argsขึ้น

เพียงพิมพ์runในคอนโซลคำสั่ง gdb เพื่อเริ่มการดีบัก


24
ตอนแรกฉันคิดว่าฉันอ่านผิด เลขคี่ --args ไปก่อนหน้าไฟล์ที่เรียกทำงานได้ แต่มันก็เป็น!
ดินขาวไฟ

8
@Kaolin - ค่าต้องมาก่อนไฟล์เรียกทำงานเนื่องจากเป็นสวิตช์สำหรับ gdb ถ้ามันเกิดขึ้นมา gdb จะแยกความแตกต่างจากข้อโต้แย้งที่คุณต้องการส่งผ่านไปยังโปรแกรมที่คุณกำลังดีบักได้อย่างไร?
codehippo

9
@codehippo: ถ้าคุณไม่ได้ระบุ--argsก็ไม่มีข้อโต้แย้งใด ๆ ที่ส่งผ่านไปยังปฏิบัติการได้ดังนั้นมันจึงไม่ค่อยชัดเจน
Lightness Races ที่ Orbit

14
ฉันเดาว่าเป็นเพราะตามธรรมเนียมargv[0]คือชื่อของปฏิบัติการ
Claudiu

3
สิ่งนี้จะเปลี่ยนเส้นทางอินพุตของgdbตัวเองไปยังofไฟล์และส่งผลให้ gdb พยายามรันคำสั่งจากมัน
unkulunkulu

4

หากคุณต้องการมีrunคำสั่งเปล่าในgdbการรันโปรแกรมด้วยการเปลี่ยนเส้นทางและการขัดแย้งคุณสามารถใช้set args:

% gdb ./a.out
(gdb) set args arg1 arg2 <file
(gdb) run

ฉันไม่สามารถทำสิ่งเดียวกันกับ--argsพารามิเตอร์ได้ทำให้gdbเกิดการเปลี่ยนเส้นทางอย่างรุนแรงเช่น

% gdb --args echo 1 2 "<file"
(gdb) show args
Argument list to give program being debugged when it is started is "1 2 \<file".
(gdb) run
...
1 2 <file
...

อันนี้เปลี่ยนเส้นทางอินพุตของ gdb จริงๆไม่ใช่สิ่งที่เราต้องการที่นี่

% gdb --args echo 1 2 <file
zsh: no such file or directory: file

1

เริ่ม GDB ในโครงการของคุณ

  1. ไปที่ไดเรกทอรีโครงการซึ่งคุณได้รวบรวมโครงการปฏิบัติการแล้ว ออกคำสั่ง gdb และชื่อของไฟล์เรียกทำงานด้านล่าง:

    gdb projectExecutablename

สิ่งนี้จะเริ่มขึ้น gdb พิมพ์ต่อไปนี้: GNU gdb (Ubuntu 7.11.1-0ubuntu1 ~ 16.04) 7.11.1 ลิขสิทธิ์ (C) 2016 มูลนิธิซอฟต์แวร์เสรีปี 2016 ............... .................................. พิมพ์ "apropos word" เพื่อค้นหาคำสั่งที่เกี่ยวข้องกับ "word" .. . การอ่านสัญลักษณ์จาก projectExecutablename ... เรียบร้อย (gdb)

  1. ก่อนที่คุณจะเริ่มโปรแกรมของคุณทำงานคุณต้องการตั้งค่าเบรกพอยต์ของคุณ คำสั่ง break อนุญาตให้คุณทำเช่นนั้น หากต้องการตั้งค่าเบรกพอยต์ที่จุดเริ่มต้นของฟังก์ชันชื่อ main:

    (gdb) b หลัก

  2. เมื่อคุณได้รับพรอมต์ (gdb) แล้วคำสั่ง run จะเริ่มต้นการเรียกใช้งานได้ หากโปรแกรมที่คุณกำลังดีบักต้องการอาร์กิวเมนต์บรรทัดคำสั่งใด ๆ คุณต้องระบุโปรแกรมเหล่านั้นในคำสั่ง run หากคุณต้องการรันโปรแกรมของฉันในไฟล์ "xfiles" (ซึ่งอยู่ในโฟลเดอร์ "mulder" ในไดเรกทอรีโครงการ) คุณจะทำสิ่งต่อไปนี้:

    (gdb) r mulder / xfiles

หวังว่านี่จะช่วยได้

คำเตือน: การแก้ปัญหานี้จะไม่ระเบิดก็จะดัดแปลงมาจากhttps://web.stanford.edu/class/cs107/guide_gdb.html คำแนะนำสั้น ๆ นี้จะได้รับการ gdb ส่วนใหญ่อาจได้รับการพัฒนาที่ Stanford University


0

มันจะดีหรือไม่ที่จะพิมพ์debugต่อหน้าคำสั่งใด ๆ เพื่อให้สามารถดีบักได้gdbระดับเชลล์?

ด้านล่างมันฟังก์ชั่นนี้ มันใช้งานได้กับ:

"$program" "$@" < <(in) 1> >(out) 2> >(two) 3> >(three)

นี่คือการเรียกที่คุณไม่สามารถควบคุมอะไรก็ได้ทุกอย่างเป็นตัวแปรสามารถมีช่องว่าง linefeeds และเชลล์เมตาอักขระ ในตัวอย่างนี้in, out, twoและthreeมีคำสั่งอื่น ๆ ที่ใช้โดยพลการหรือข้อมูลการผลิตซึ่งจะต้องไม่ได้รับอันตราย

bashฟังก์ชั่นดังต่อไปนี้จะเรียกใช้gdbเกือบหมดจดในสภาพแวดล้อมเช่น [ สรุป ]

debug()
{
  1000<&0 1001>&1 1002>&2 \
  0</dev/tty 1>/dev/tty 2>&0 \
  /usr/bin/gdb -q -nx -nw \
  -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" exec' \
  -ex r \
  --args "$@";
}

ตัวอย่างเกี่ยวกับวิธีใช้: เพียงพิมพ์ debugด้านหน้า:

ก่อน:

p=($'\n' $'I\'am\'evil' "  yay  ")
"b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)

หลังจาก:

p=($'\n' $'I\'am\'evil' "  yay  ")
debug "b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)

แค่นั้นแหละ. gdbตอนนี้ก็แน่นอนไม่มีเกมง่ายๆที่จะแก้ปัญหาด้วย ยกเว้นรายละเอียดเล็กน้อยหรือมากกว่านั้น:

  • gdbไม่เลิกโดยอัตโนมัติและด้วยเหตุนี้ทำให้ IO gdbเปลี่ยนเส้นทางเปิดให้บริการจนถึงคุณออก แต่ฉันเรียกคุณลักษณะนี้ว่า

  • คุณไม่สามารถส่งผ่านไปยังโปรแกรมเช่นเดียวกับargv0 exec -a arg0 command argsต่อไปนี้ควรทำเคล็ดลับนี้: หลังจากexec-wrapperการเปลี่ยนแปลงไป"exec"exec -a \"\${DEBUG_ARG0:-\$1}\"

  • มี FDs มากกว่า 1,000 เปิดซึ่งโดยปกติจะปิด หากนี่เป็นปัญหาให้เปลี่ยน0<&1000 1>&1001 2>&1002เป็นอ่าน0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-

  • คุณไม่สามารถเรียกใช้ตัวแก้ไขสองตัวพร้อมกัน อาจมีปัญหาหากคำสั่งอื่นใช้/dev/tty(หรือ STDIN) ในการแก้ไขปัญหาที่แทนที่ด้วย/dev/tty "${DEBUGTTY:-/dev/tty}"ในบางประเภท TTY อื่น ๆtty; sleep infแล้วใช้พิมพ์ TTY (i. E. /dev/pts/60) DEBUGTTY=/dev/pts/60 debug command arg..สำหรับการแก้จุดบกพร่องในขณะที่ นั่นคือพลังของเชลล์ชินกับมัน!

ฟังก์ชั่นอธิบาย:

  • 1000<&0 1001>&1 1002>&2 ย้าย 3 FDs แรกออกไป
    • สมมติว่า FDs 1,000, 1001 และ 1002 นั้นฟรี
  • 0</dev/tty 1>/dev/tty 2>&0เรียกคืน 3 FDs แรกให้ชี้ไปที่ TTY ปัจจุบันของคุณ gdbเพื่อให้คุณสามารถควบคุม
  • /usr/bin/gdb -q -nx -nwรันการgdbเรียกใช้gdbบนเชลล์
  • -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" สร้าง wrapper เริ่มต้นซึ่งจะกู้คืน 3 FDs แรกซึ่งถูกบันทึกไว้ที่ 1,000 ขึ้นไป
  • -ex r เริ่มโปรแกรมโดยใช้ exec-wrapper
  • --args "$@" ผ่านการขัดแย้งตามที่กำหนด

มันไม่ง่ายเลยเหรอ?

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