7

ptrace された子プロセスのメモリ空間に (読み取り操作と書き込み操作の両方で) アクセスする効率的な方法を探しています。アクセスされるブロックのサイズは、数バイトから数メガバイトまで変化する可能性があるため、一度に 1 ワードだけを読み取り、呼び出されるたびにコンテキストを切り替えるptrace 呼び出しをPTRACE_PEEKDATAandで使用することは、無意味なリソースの浪費のように思えます。PTRACE_POKEDATAただし、私が見つけた唯一の代替ソリューションは/proc/<pid>/memファイルでしたが、それはずっと前に読み取り専用になりました。

その仕事をする他の(比較的簡単な)方法はありますか?理想的な解決策は、子プロセスのアドレス空間を親プロセスと何らかの方法で共有し、単純な memcpy 呼び出しを使用して必要なデータを双方向にコピーすることですが、その方法とどこから始めればよいかわかりません。

何か案は?

4

6 に答える 6

4

これが Linux の場合 (タグが示すように)、フラグを使用clone()して、子のアドレス空間全体を親と共有できます。CLONE_VM2 つのプロセスが同じ VM スペースを共有するため、2 つのプロセス間ですべての変更がすぐに表示され、基本的にオーバーヘッドはゼロになります。

exec()これは、子ではできないことを意味します。両方のプロセスの VM スペースを置き換えるためです。

于 2009-08-10T22:00:58.087 に答える
1

子プロセスとそのソースコードを管理していますか?その場合は、共有メモリの使用を検討できます。

于 2009-08-09T23:14:02.783 に答える
1

何らかのデバッグ関数を ptrace プロセスに挿入し、ptrace_setregs を介して呼び出すことを検討してください。gdb が ptraced プロセスの任意の機能を実行する方法のようなもの。

また、LD_PRELOAD を介してプロセスにコードを挿入することもできます。シグナルを使用して、ptrace なしで動作させることもできます。

upd1: Gdb インジェクションまたは「下位関数呼び出し」はかなり複雑です。ファイル gdb-6.6.50.20070809›gdb›infcall.c の関数 call_function_by_hand を参照してください: http://sources.debian.net/src/gdb/7.6.2-1/gdb/infcall.c?hl=462#L462

/* All this stuff with a dummy frame may seem unnecessarily complicated
   (why not just save registers in GDB?).  The purpose of pushing a dummy
   frame which looks just like a real frame is so that if you call a
   function and then hit a breakpoint (get a signal, etc), "backtrace"
   will look right.  Whether the backtrace needs to actually show the
   stack at the time the inferior function was called is debatable, but
   it certainly needs to not display garbage.  So if you are contemplating
   making dummy frames be different from normal frames, consider that.  */

/* Perform a function call in the inferior.
   ARGS is a vector of values of arguments (NARGS of them).
   FUNCTION is a value, the function to be called.
   Returns a value representing what the function returned.
   May fail to return, if a breakpoint or signal is hit
   during the execution of the function.

   ARGS is modified to contain coerced values.  */

struct value *
call_function_by_hand (struct value *function, int nargs, struct value **args)
{
...
  frame = get_current_frame ();
  gdbarch = get_frame_arch (frame);

  if (!gdbarch_push_dummy_call_p (gdbarch))
    error (_("This target does not support function calls."));

  /* A cleanup for the inferior status.
     This is only needed while we're preparing the inferior function call.  */
  inf_status = save_infcall_control_state ();
  inf_status_cleanup
    = make_cleanup_restore_infcall_control_state (inf_status);

  /* Save the caller's registers and other state associated with the
     inferior itself so that they can be restored once the
     callee returns.  To allow nested calls the registers are (further
     down) pushed onto a dummy frame stack.  Include a cleanup (which
     is tossed once the regcache has been pushed).  */
  caller_state = save_infcall_suspend_state ();
  make_cleanup_restore_infcall_suspend_state (caller_state);
...
    sp = push_dummy_code (gdbarch, sp, funaddr, args, nargs,
                  target_values_type, &real_pc, &bp_addr,
                  get_current_regcache ());
... pass args ...
  /* Create the dummy stack frame.  Pass in the call dummy address as,
     presumably, the ABI code knows where, in the call dummy, the
     return address should be pointed.  */
  sp = gdbarch_push_dummy_call (gdbarch, function, get_current_regcache (),
                bp_addr, nargs, args,
                sp, struct_return, struct_addr);
...
  /* Everything's ready, push all the info needed to restore the
     caller (and identify the dummy-frame) onto the dummy-frame
     stack.  */
  dummy_frame_push (caller_state, &dummy_id);
... 
    /* Run the inferior until it stops.  */

    e = run_inferior_call (tp, real_pc);
  }
于 2010-02-07T05:43:21.957 に答える
0

子プロセスを制御している場合は、問題のメモリに書き込むことができるデバッグインターフェイスを追加できますか?

于 2009-09-26T08:09:46.897 に答える
0

/proc/<pid>/maps読み取りの場合、ファイルを解析して対象のメモリ領域の仮想アドレスを取得するのが最善の策です。

次に、関心のある領域で大きなバッファを開いて呼び出しを/proc/<pid>/mem実行することで、これらを読み取ることができます。read()

書き込みについては、ブロック全体を書き込む簡単な方法をまだ見つけていません。これは、子プロセスのロックと安定性に関係していると思います。呼び出しを介してptrace()これを保証できますが、別のプロセスのメモリに直接アクセスすることはできません。私は通常、ptrace(PTRACE_POKEDATA, ...)Windows のWriteProcessMemory().

于 2010-02-14T05:31:16.480 に答える
0

clone または mmap は、探しているものです。2 つのプロセス間で一時ファイルを mmap し、そのメモリ領域を使用してデータをやり取りします。

于 2010-03-26T21:50:55.737 に答える