3

プロセスコール(nanosleep()など)にあるときに、ptrace(PTRACE_ATTACH ...)を使用してプロセスに接続しています。PTRACE_GETREGSを使用してレジスタの内容を取得できます。eipは予想される場所(__kernel_vsyscall内)にあります。ただし、eaxおよびorig_eaxレジスタには予期しない内容が含まれています。eaxには通常-516が含まれ、orig_eaxは通常0です。

これは私が使用したテストプログラムです(http://www.linuxjournal.com/article/6210から取得し、わずかに変更しました):

    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/ptrace.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <sys/user.h>

    int main(int argc, char *argv[])
    {
        pid_t traced_process;
        struct user_regs_struct regs;
        long ins;
        if(argc != 2) {
            printf("Usage: %s <pid to be traced>\n",
                   argv[0]);
            exit(1);
        }
        traced_process = atoi(argv[1]);
        ptrace(PTRACE_ATTACH, traced_process,
               NULL, NULL);
        wait(NULL);
        ptrace(PTRACE_GETREGS, traced_process,
               NULL, &regs);
        printf("eax: %lx (%d); orig_eax: %lx\n",
               regs.eax, (int)regs.eax, regs.orig_eax);
        ins = ptrace(PTRACE_PEEKTEXT, traced_process,
                     regs.eip, NULL);
        printf("EIP: %lx Instruction executed: %lx\n",
               regs.eip, ins);
        ptrace(PTRACE_DETACH, traced_process,
               NULL, NULL);
        return 0;
    }

別の端末で実行されている「sleep10000」コマンドに接続する場合の出力:

    eax: fffffdfc (-516); orig_eax: 0
    EIP: b7711424 Instruction executed: c3595a5d

eaxの値はどういう意味ですか?orig_eaxに元のシステムコール番号(162など)が含まれていないのはなぜですか?この場合、実際にシステムコール番号を取得するにはどうすればよいですか?

また、gdbが「print $ orig_eax」に対して「162」を正しく表示するのはなぜですか?

ところで。これは、カーネル3.2.0を使用するUbuntu12.04にあります。

  • uname -a: "Linux edgebox 3.2.0-24-generic-pae#37-Ubuntu SMP Wed Apr 25 10:47:59 UTC 2012 i686 athlon i386 GNU / Linux"
  • / proc / cpuinfo:「AMDAthlon(tm)IINeoK345デュアルコアプロセッサ」
  • ファイルwhich sleep: "/ bin / sleep:ELF 32ビットLSB実行可能ファイル、Intel 80386、バージョン1(SYSV)、動的リンク(共有ライブラリを使用)、GNU / Linux 2.6.24、BuildID [sha1] = 0x0965431bde4d183eaa2fa3e3989098ce46b92129、削除済み"。

つまり、これは32ビットPAEカーネルと64ビットCPUへの32ビットUbuntuインストールです。

4

3 に答える 3

1

プロセスに接続すると、進行中のシステムコールを中断する信号がプロセスに送信されました。ほとんどのシステムコールは、これが発生した場合に-EINTRを返すだけであり、必要に応じてユーザースペースコードがそれらを再起動することを期待します。自動的に再起動できる他のシステムコールもありますが、それはより大きなトピックです。

nanosleep()が1つである一部のシステムコールの場合、プロセスは指定された時間の一部ですでにスリープしているため、最初から再起動するのではなく、残りの時間だけスリープする必要があります。これを実現するために、各スレッドにはカーネル空間に「再起動ブロック」があります。システムコールが中断されると、再起動ブロックが埋められ、-516(ERESTART_RESTARTBLOCK)が返されます。カーネルはこのリターンコードを特別に扱います。つまり、PCをsyscallの前に巻き戻し、syscall番号を「restart_syscall」(アーキテクチャでは0)に変更します。プロセスが再起動されると、restart_syscallが呼び出され、restartブロックを使用して何をすべきかがわかります。

この再起動は、通常はユーザーには見えないようにすることを目的としていますが、ptraceはそれを見つける1つの方法です。ただし、GDBがorig_eaxの正しい値を取得できるかどうかはわかりません。

于 2014-09-01T16:16:43.830 に答える
0

これは、カーネル3.2.0を搭載したUbuntu12.04にあります。

これは、システムを一意に識別するものではありません。どのプロセッサですか?

私の水晶玉は、sleepあなたが呼び出しているのは64ビットプログラムであるが、トレーサープログラムはそうではないことを教えてくれます。またはその逆。

于 2012-06-29T21:30:50.480 に答える
0

スリープ中のプロセスがptrace(PTRACE_ATTACH)によって停止されると、トレーサープロセスはレジスター(user_regs_struct)情報を取得できます。システムコール番号は162で、これはsys_nanosleepです。eax = -516は、この中断されたsyscallの戻り値を示します。

于 2015-02-04T02:15:45.440 に答える