18

32ビットLinuxカーネルでカーネルモジュールをコンパイルすると、次のようになります。

"__udivdi3" [mymodule.ko] undefined!
"__umoddi3" [mymodule.ko] undefined!

64ビットシステムではすべて問題ありません。私の知る限り、この理由は、64ビットの整数除算とモジュロが32ビットのLinuxカーネル内でサポートされていないためです。

64ビット演算を発行するコードを見つけるにはどうすればよいですか。「/」が32ビット幅か64ビット幅かを簡単に確認できないため、手動で見つけるのは困難です。「通常の」関数が定義されていない場合、それらをgrepできますが、ここでは不可能です。参照を検索する別の良い方法はありますか?ある種の「マシンコードgrep」?

このモジュールは、数千行のコードで構成されています。すべての行を手動でチェックすることはできません。

4

3 に答える 3

24

まず、do_divマクロを使用して64ビット除算を行うことができます。(プロトタイプはuint32_t do_div(uint64_t dividend, uint32_t divisor)であり、" dividend"は複数回評価される可能性があることに注意してください。

{
    unsigned long long int x = 6;
    unsigned long int y = 4;
    unsigned long int rem;

    rem = do_div(x, y);
    /* x now contains the result of x/y */
}

long long intさらに、コード内で(または)型の使用法を見つけることができるはずです。あるいは、フラグを使用しuint64_tてモジュールをビルドし、それを使用してソースの注釈付き分解を取得することもできます。-gobjdump -S

注:これは2.6カーネルに適用されます。これより低いものについては、使用状況を確認していません。

于 2009-06-30T14:00:18.773 に答える
5

実際、64ビットの整数除算とモジュロ32ビットのLinuxカーネル内でサポートされています。ただし、これを行うには正しいマクロを使用する必要があります(最近、新しいより優れたマクロがIIRCで作成されたため、カーネルのバージョンによって異なります)。マクロは、コンパイルするアーキテクチャに関係なく、最も効率的な方法で正しい処理を実行します。

それらが使用されている場所を見つける最も簡単な方法は、(@ shodanexの回答で述べられているように)アセンブリコードを生成することです。IIRC、そうする方法は次のようなものですmake directory/module.s(すでに渡さなければならないパラメータと一緒にmake)。.o次の最も簡単な方法は、ファイルを(のようなもので)分解することですobjdump --disassemble。どちらの方法でも、呼び出しが生成されている関数が得られます(また、アセンブリの読み取り方法を知っている場合は、関数内のどこで分割が行われているのかについての一般的な考え方がわかります)。

于 2009-06-30T13:53:04.200 に答える
4

コンパイル段階の後、文書化されたアセンブリを取得して、それらの関数が呼び出されたかどうかを確認できるはずです。CFLAGSをいじって、-Sフラグを追加してみてください。コンパイルは組み立て段階で停止する必要があります。次に、アセンブリファイルで問題のある関数呼び出しをgrepできます。

于 2009-06-30T13:42:31.493 に答える