Bagaimana cara menyampaikan argumen dan mengarahkan stdin dari file ke program yang berjalan di gdb?

210

Saya biasanya menjalankan program sebagai:

./a.out arg1 arg2 <file

Saya ingin men-debug menggunakan gdb.

Saya mengetahui set argsfungsinya, tetapi itu hanya berfungsi dari prompt gdb.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber

Jawaban:

136

Lewati argumen ke runperintah dari dalam gdb.

$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t
moinudin
sumber
3
radalah kependekan dari rundan Anda dapat mengikutinya dengan argumen apa pun. Seperti dalam pertanyaan ini, bisa jadi: r arg1 arg2 <fileatau bisa jugarun arg1 arg2 <file
phyatt
Bagi saya itu tidak berhasil. Kemudian saya mencoba $ gdb ./a.outmaka (gdb) r < t arg1 arg2yang bekerja dengan baik bagi saya. Dalam kasus saya a.out = nft arg1 = import arg2 = json dant = file containing json rules
mystictot
410

Kamu bisa melakukan ini:

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

Yang ajaib itu --args.

Cukup ketik runkonsol perintah gdb untuk memulai debugging.

rubenvb
sumber
24
Saya pikir saya salah membaca ini pada awalnya; aneh bahwa --args berjalan sebelum dieksekusi. Tapi begitulah!
Kaolin Fire
8
@ Kaolin --args harus ada sebelum dieksekusi karena itu adalah saklar untuk gdb. Jika itu datang setelahnya, bagaimana gdb membedakannya dari argumen yang ingin Anda sampaikan ke executable yang sedang Anda debug?
codehippo
9
@codehippo: Ya, jika Anda tidak menentukan --argsmaka tidak ada argumen yang diteruskan ke executable, jadi hampir tidak ambigu.
Lightness Races in Orbit
14
Saya menduga itu karena secara konvensional argv[0]adalah nama yang dapat dieksekusi
Claudiu
3
ini akan mengarahkan input gdbdirinya ke offile dan menghasilkan gdb yang mencoba mengeksekusi perintah darinya
unkulunkulu
4

Jika Anda ingin memiliki runperintah kosong gdbuntuk menjalankan program Anda dengan pengalihan dan argumen, Anda dapat menggunakan set args:

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

Saya tidak dapat mencapai perilaku yang sama dengan --argsparameter, gdbdengan hebat lolos dari pengalihan, yaitu

% 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
...

Yang ini sebenarnya mengarahkan ulang input gdb itu sendiri, bukan yang sebenarnya kita inginkan di sini

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

Mulai GDB di proyek Anda.

  1. Pergi ke direktori proyek, di mana Anda telah menyusun executable proyek. Keluarkan perintah gdb dan nama yang dapat dieksekusi seperti di bawah ini:

    gdb projectExecutablename

Ini memulai gdb, mencetak yang berikut: GNU gdb (Ubuntu 7.11.1-0ubuntu1 ~ 16.04) 7.11.1 Hak cipta (C) 2016 Free Software Foundation, Inc. ............... .................................. Ketikkan "kata apropos" untuk mencari perintah yang terkait dengan "kata" .. Membaca simbol dari projectExecutablename ... selesai. (gdb)

  1. Sebelum Anda mulai menjalankan program, Anda ingin mengatur breakpoint Anda. Perintah break memungkinkan Anda untuk melakukannya. Untuk mengatur breakpoint di awal fungsi bernama main:

    (gdb) b utama

  2. Setelah Anda memiliki prompt (gdb), perintah run mulai menjalankan yang dapat dieksekusi. Jika program yang Anda debug membutuhkan argumen baris perintah, Anda menentukannya untuk menjalankan perintah. Jika Anda ingin menjalankan program saya pada file "xfiles" (yang ada di folder "mulder" di direktori proyek), Anda akan melakukan hal berikut:

    (gdb) r mulder / xfiles

Semoga ini membantu.

Penafian: Solusi ini bukan milik saya, ini diadaptasi dari https://web.stanford.edu/class/cs107/guide_gdb.html Panduan singkat untuk gdb ini, kemungkinan besar, dikembangkan di Universitas Stanford.

Ehsan
sumber
0

Bukankah lebih baik mengetikkan saja debugdi depan perintah apa saja untuk dapat men-debug dengan gdbpada tingkat shell?

Di bawahnya fungsi ini. Ia bahkan bekerja dengan mengikuti:

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

Ini adalah panggilan di mana Anda tidak dapat mengontrol apa pun, semuanya variabel, dapat berisi spasi, umpan baris, dan karakter meta shell. Dalam contoh ini, in, out, two, dan threesewenang-wenang perintah lain yang mengkonsumsi atau data hasil yang tidak boleh dirugikan.

Berikut bashmemanggil fungsi gdbhampir bersih di lingkungan seperti [ Intisari ]:

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 "$@";
}

Contoh tentang cara menerapkan ini: Cukup ketik debugdi depan:

Sebelum:

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

Setelah:

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

Itu dia. Sekarang ini adalah no-brainer untuk di-debug gdb. Kecuali untuk beberapa detail atau lebih:

  • gdbtidak berhenti secara otomatis dan karenanya menjaga pengalihan IO terbuka sampai Anda keluar gdb. Tetapi saya menyebutnya fitur.

  • Anda tidak dapat dengan mudah beralih argv0ke program seperti dengan exec -a arg0 command args. Berikut ini harus melakukan trik ini: Setelah exec-wrapperberubah "execmenjadi "exec -a \"\${DEBUG_ARG0:-\$1}\".

  • Ada FD di atas 1000 terbuka, yang biasanya ditutup. Jika ini masalah, ubah 0<&1000 1>&1001 2>&1002untuk membaca0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-

  • Anda tidak dapat menjalankan dua debugger secara paralel. Mungkin juga ada masalah, jika beberapa perintah lain mengkonsumsi /dev/tty(atau STDIN). Untuk memperbaikinya, ganti /dev/ttydengan "${DEBUGTTY:-/dev/tty}". Dalam beberapa jenis TTY lain tty; sleep infdan kemudian gunakan TTY yang dicetak (i. E. /dev/pts/60) untuk debugging, seperti pada DEBUGTTY=/dev/pts/60 debug command arg... Itulah Kekuatan Shell, biasakanlah!

Fungsi menjelaskan:

  • 1000<&0 1001>&1 1002>&2 menjauh 3 FD pertama
    • Ini mengasumsikan, bahwa FDs 1000, 1001 dan 1002 gratis
  • 0</dev/tty 1>/dev/tty 2>&0mengembalikan 3 FD pertama untuk menunjuk ke TTY Anda saat ini. Jadi kamu bisa mengendalikan gdb.
  • /usr/bin/gdb -q -nx -nwmenjalankan gdbmemanggil gdbpada shell
  • -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" membuat pembungkus startup, yang mengembalikan 3 FD pertama yang disimpan hingga 1000 ke atas
  • -ex r memulai program menggunakan exec-wrapper
  • --args "$@" melewati argumen seperti yang diberikan

Bukankah itu mudah?

Tino
sumber