web-dev-qa-db-ja.com

引数を渡し、ファイルからgdinで実行されるプログラムにstdinをリダイレクトする方法は?

私は通常、プログラムを次のように実行します:

./a.out arg1 arg2 <file

Gdbを使用してデバッグしたいと思います。

set args機能は知っていますが、それはgdbプロンプトからのみ機能します。

207
user277465

引数をgdb内からrunコマンドに渡します。

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

あなたはこれを行うことができます:

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

魔法のビットは--argsです。

Gdbコマンドコンソールでrunと入力するだけで、デバッグを開始できます。

408
rubenvb

rungdbコマンドをそのままにして、リダイレクトと引数を使用してプログラムを実行する場合は、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
4
unkulunkulu

プロジェクトでGDBを起動します。

  1. プロジェクトの実行可能ファイルを既にコンパイルしたプロジェクトディレクトリに移動します。次のようにコマンドgdbと実行可能ファイルの名前を発行します。

    gdb projectExecutablename

これによりgdbが起動し、次が出力されます。GNU gdb(Ubuntu 7.11.1-0ubuntu1〜16.04)7.11.1 Copyright(C)2016 Free Software Foundation、Inc. ......... ........................................「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のこの短いガイドは、おそらくスタンフォード大学で開発されました。

1
Ehsan

シェルレベルでdebugname__を使用してデバッグできるようにするには、コマンドの前にgdbname__と入力するだけでいいのではないでしょうか。

その下にこの関数。以下でも動作します:

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

これは、何も制御できない呼び出しであり、すべてが可変であり、スペース、改行、およびシェルメタキャラクターを含めることができます。この例では、inname __、outname __、twoname__、およびthreename__は、損傷してはならないデータを消費または生成する任意の他のコマンドです。

次のbashname__関数は、そのような環境[_ Gist ]でほぼきれいにgdbname__を呼び出します。

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

これを適用する方法の例:前にdebugname__と入力するだけです:

前:

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)

それでおしまい。これで、gdbname__でデバッグするのは非常に簡単です。いくつかの詳細を除いて:

  • gdbname__は自動的に終了しないため、gdbname__を終了するまでIOリダイレクトを開いたままにします。しかし、これを機能と呼びます。

  • argv0のようにexec -a arg0 command argsをプログラムに簡単に渡すことはできません。以下は、このトリックを行う必要があります。exec-wrapperの後に、"exec"exec -a \"\${DEBUG_ARG0:-\$1}\"に変更します。

  • 1000を超えるFDが開いており、通常は閉じています。これが問題になる場合は、0<&1000 1>&1001 2>&1002を変更して0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-を読み取ってください

  • 2つのデバッガーを並行して実行することはできません。他のコマンドが/dev/tty(またはSTDIN)を消費する場合にも問題が発生する可能性があります。これを修正するには、/dev/tty"${DEBUGTTY:-/dev/tty}"に置き換えます。他のTTYでtty; sleep infと入力し、/dev/pts/60のように、デバッグ用に印刷されたTTY(i。E. DEBUGTTY=/dev/pts/60 debug command arg..)を使用します。それがシェルの力です、それに慣れてください!

機能の説明:

  • 1000<&0 1001>&1 1002>&2は最初の3つのFDを移動します
    • これは、FD 1000、1001、および1002が無料であることを前提としています
  • 0</dev/tty 1>/dev/tty 2>&0は、現在のTTYを指すように最初の3つのFDを復元します。したがって、gdbname__を制御できます。
  • /usr/bin/gdb -q -nx -nwgdbname__を実行し、シェルでgdbname__を呼び出します
  • -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\""は、1000以上に保存された最初の3つのFDを復元するスタートアップラッパーを作成します
  • -ex rは、exec-wrapperを使用してプログラムを開始します
  • --args "$@"は与えられた引数を渡します

簡単じゃなかった?

0
Tino