1

私の主な目的は、プログラムがクラッシュしたときに、LBR レジスタによって維持されている最後の 16 分岐のアドレス値を取得することです。今まで2つの方法を試しました-

1) msr-tools これにより、コマンド ラインから msr 値を読み取ることができます。C プログラム自体からシステム コールを作成し、値を読み取ろうとします。しかし、レジスタ値は、プログラム自体のアドレスに関連していないようです。ほとんどの場合、レジスターはシステム コードの他のブランチから汚染されています。リング 0 とファー ジャンプの分岐の記録をオフにしてみました。しかし、それは役に立ちません。まだ無関係な値を取得しています。

2) カーネル モジュールを介したアクセス わかりました、msr レジスタに直接アクセスし、おそらくレジスタ汚染を回避するために、非常に単純なモジュールを作成しました (これまでにこれを行ったことはありません)。

これが私が持っているものです -

#define LBR 0x1d9 //IA32_DEBUGCTL MSR
                  //I first set this to some non 0 value using wrmsr (msr-tools)
static void __init do_rdmsr(unsigned msr, unsigned unused2)
{
    uint64_t msr_value;
    __asm__ __volatile__ ("                 rdmsr"
                    : "=A" (msr_value)
                    : "c" (msr)
                    );

    printk(KERN_EMERG "%lu \n",msr_value);
}
static int hello_init(void)
{
    printk(KERN_EMERG "Value is ");
    do_rdmsr (LBR,0);
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_EMERG "End\n");
}

module_init(hello_init);
module_exit(hello_exit);

しかし、問題は、dmesg を使用して出力を読み取るたびに、

Value is 0 

(私は他のレジスタを試しました - それは常に0になります)

ここで私が忘れていることはありますか?何か助けはありますか?ありがとう

4

2 に答える 2

3

以下を使用します。

unsigned long long x86_get_msr(int msr)
{
    unsigned long msrl = 0, msrh = 0;

    /* NOTE: rdmsr is always return EDX:EAX pair value */
    asm volatile ("rdmsr" : "=a"(msrl), "=d"(msrh) : "c"(msr));

    return ((unsigned long long)msrh << 32) | msrl;
}
于 2012-04-23T07:08:26.390 に答える