私はWindowsからLinuxにプログラムを移植しようとしています。
Linux上に「本物」のReadProcessMemory
がないことがわかったときに問題が発生しました。代替案を探して、強力なプロセスデバッガであるptrace
が見つかりました。
私はすぐにプログラムで使用する前に、ptrace
をテストするために、C++で小さなコンソールアプリケーションを2つコーディングしました。Linux:プロセス(SIGSTOP)を停止/一時停止せずにptraceを使用する方法はありますか?
でTestApp
これはtraceeあります。 50ミリ秒ごとに2つの整数を印刷し、毎回その値を1ずつ増加させます。
#include <QCoreApplication>
#include <QThread>
#include <iostream>
using namespace std;
class Sleeper : public QThread
{
public:
static void usleep(unsigned long usecs){QThread::usleep(usecs);}
static void msleep(unsigned long msecs){QThread::msleep(msecs);}
static void sleep(unsigned long secs){QThread::sleep(secs);}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int value = 145;
int i = 0;
do {
cout << "i: " << i << " " << "Value: " << value << endl;
value++;
i++;
Sleeper::msleep(50);
} while (true);
return a.exec();
}
MemoryTest
これはトレーサです。プロセス名を尋ねて、コマンドpidof -s
を使用してPIDを取得すると、ptrace
がプロセスにアタッチされ、メモリアドレスの値が500ミリ秒ごとに10回取得されます。
#include <QCoreApplication>
#include <QThread>
#include <iostream>
#include <string>
#include <sys/ptrace.h>
#include <errno.h>
using namespace std;
class Sleeper : public QThread
{
public:
static void usleep(unsigned long usecs){QThread::usleep(usecs);}
static void msleep(unsigned long msecs){QThread::msleep(msecs);}
static void sleep(unsigned long secs){QThread::sleep(secs);}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
char process_name[50];
cout << "Process name: ";
cin >> process_name;
char command[sizeof(process_name) + sizeof("pidof -s ")];
snprintf(command, sizeof(command), "pidof -s %s", process_name);
FILE* shell = popen(command, "r");
char pidI[sizeof(shell)];
fgets(pidI, sizeof(pidI), shell);
pclose(shell);
pid_t pid = atoi(pidI);
cout << "The PID is " << pid << endl;
long status = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
cout << "Status: " << status << endl;
cout << "Error: " << errno << endl;
unsigned long addr = 0x; // Example address, not the true one
int i = 0;
do {
status = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
cout << "Status: " << status << endl;
cout << "Error: " << errno << endl;
i++;
Sleeper::msleep(500);
} while (i < 10);
status = ptrace(PTRACE_DETACH, pid, NULL, NULL);
cout << "Status: " << status << endl;
cout << "Error: " << errno << endl;
return a.exec();
}
すべてが正常に動作しますが、ptrace
はそれから外れるまででTestAppは(SIGSTOP)一時停止されています。
また、プロセスにアタッチすると、ステータスは0、エラーは2です。メモリアドレス値を最初に取得しようとすると、ステータス-1とエラー3で失敗します。これは正常ですか?
ptraceがSIGSTOPシグナルをプロセスに送信しないようにする方法はありますか? は、私はすでに代わりPTRACE_ATTACH
のPTRACE_SEIZE
を使用してみましたが、それは動作しません:状態-1とエラー3
更新:を前にMemoryTestでSleeper
の使用「を行い、一方で」ループは最初の問題を修正秒、ミリ秒またはマイクロ秒の値が0であっても、メモリアドレス値を取得できます。なぜですか?
あなたの答えをありがとうございました。もっと簡単な方法を使いたいので、私は/ procを見ていませんでした。可能でない場合は、メモリマップファイルを試してみます。私はDebian 8 x64を使用していますが、これは問題ではありません。私の推測では、 'PTRACE_SEIZE'は' PTRACE_ATTACH'とは別の方法で使用する必要がありますが、特定のドキュメントは見つかりません。 –
2つのコメントを申し訳ありません。コメントを編集しましたが、5分後には更新できなくなりました。 'addr'値は単なる例であり、正しいものはうまくいきます。エラーコードについては、プログラムが正常に動作するため、問題ではありません。 –
コード内のあなたのコメントは、アドレスが例であると言っています。 Stack Overflowで私の評判を築こうとしているので、それが役に立ったら、私の答えを「受け入れてください」。 ptrace呼び出しが/ procファイルを操作するより簡単になることは間違いありません。しかし、/ proc領域にはたくさんの情報があります。あなたがLinuxのデバッグとプロセスの構造について学んでいるなら、それは研究に有益な領域になります。 PTRACE_CONTはプログラムで動作しましたか? –