1

OSX用のkextとして仮想USBバス(Linuxボックスとネットワーク経由で通信)を構築します。メイン クラスは IOUSBControllerV3 から派生します。

10.6 32 ビット、10.7.5 64 ビット、10.8 64 ビットでは動作しますが、10.7.5 32 ビットでは (a?) 純粋仮想機能が原因でロードできませんでした。kextutil は私にこれを教えてくれました。

同じシステムで kext をコンパイル (Xcode 4.6) し、システムまたは SDK のバージョンをターゲットとする多くのバリエーションを試しましたが、問題はまだ残っていますか?

特に純粋仮想関数のコンテキストでは、基本クラスのヘッダーにいくつかの #ifdef LP64の違いがあることを私は知っています。

しかし、純粋仮想関数のオーバーロードを 2 日間比較して比較した結果、なぜ 32 ビットだけで問題が発生するのかわかりません。

同じコードは他のシステムでも機能しますが、Lion 32 ビットでは機能しません。

すべてのヒントを前もって感謝します。

よろしくマーカス

=========== ターミナル出力:

MacProTest:Developer ms$ sudo kextutil -t -v 2   MaCute.kext
Password:
Notice: MaCute.kext has debug properties set.
MaCute.kext appears to be loadable (not including linkage for on-disk libraries).
Loading MaCute.kext.
Reading load info for 13 kexts.
Created mkext for architecture i386 containing 1 kexts.
Loading MaCute.kext.
(kernel) Received request from user space to load kext de.seh.utn.MaCute.
(kernel) Loading kext de.seh.utn.MaCute.
(kernel) Allocated link buffer for kext de.seh.utn.MaCute at 0x1507000 (200704 bytes).
(kernel) kxld[de.seh.utn.MaCute]: This kext calls a pure virtual function. Make sure your kext's OSObject-derived classes implement all pure virtual functions.
(kernel) Can't load kext de.seh.utn.MaCute - link failed.
(kernel) Failed to load executable for kext de.seh.utn.MaCute.
(kernel) Kext de.seh.utn.MaCute failed to load (0xdc008016).
(kernel) Failed to load kext de.seh.utn.MaCute (error 0xdc008016).
Failed to load MaCute.kext - (libkern/kext) link error.
Failed to load MaCute.kext - (libkern/kext) link error.
Check library declarations for your kext with kextlibs(8).
4

1 に答える 1

1

ヘッダー ファイルに明らかなIOUSBControllerV3.h原因が見つからないため、関連するソース コードを見つけるためにエラー メッセージを Google で検索することにしました。kxld_reloc.cの関数までさかのぼりましcheck_for_direct_pure_virtual_call()た。

    entry = kxld_vtable_get_entry_for_offset(relocator->current_vtable, 
        offset, relocator->is_32_bit);
    require_action(!entry || !entry->patched.name ||
        !kxld_sym_name_is_pure_virtual(entry->patched.name),
        finish, rval=KERN_FAILURE;
        kxld_log(kKxldLogLinking, kKxldLogErr, 
            kKxldLogDirectPureVirtualCall));

kKxldLogDirectPureVirtualCallそのエラーとして#definedです。

私があなたなら、その osx バージョン (1699.32.7) の xnu ソース パッケージをダウンロードし、このサイトの手順に従って独自のカーネル バイナリをビルドします。次に、entry->patched.nameアサーション条件が失敗した場合に出力するように上記の関数を変更するため、次のrequire_action()行の前に挿入します。

if (entry && entry->patched.name && kxld_sym_name_is_pure_virtual(entry->patched.name))
printf("pure virtual function called by kext: %s\n", entry->patched.name);

次に、新しいカーネルを再構築して起動します。これにより、関数の(マングルされた)名前がカーネルログに出力されるはずです。かなりの努力ですが、そこにたどり着くと思います!

アップデート:

コメントから、私たちがまだそこに達していないことは明らかです。i386 では、check_for_direct_pure_virtual_call()から呼び出されgeneric_process_reloc()、純粋な仮想チェックが失敗した場合に失敗を報告します。

rval = check_for_direct_pure_virtual_call(relocator, instr_data);
require_noerr(rval, finish);

この関数には特に役立つものは何もありませんが、2 つの関数から呼び出されます:kxld_relocator_process_sect_reloc()kxld_relocator_process_table_reloc(). この場合、どちらが当てはまるかわかりませんが、両方のコードは非常に似ているため、デバッグ出力を使用して同じ方法で両方を変更できます。

rval = relocator->process_reloc(relocator, instruction, reloc->length, 
    reloc->pcrel, base_pc, link_pc, link_disp, reloc->reloc_type, target, 
    pair_target, relocator->swap);
require_noerr(rval, finish);

これら 2 つのステートメントの間にコードを挿入します。1 つ目は失敗した再配置呼び出しで、2 つ目は関数から抜け出します。失敗をキャッチし、それらのデバッグ出力を生成したいと考えています。したがって、次のようなものです。

rval = relocator->process_reloc(relocator, instruction, reloc->length, 
    reloc->pcrel, base_pc, link_pc, link_disp, reloc->reloc_type, target, 
    pair_target, relocator->swap);

if (rval)
{
  // try to find the symbol corresponding to this relocation entry
  KXLDSym* sym = kxld_reloc_get_symbol(relocator, reloc, NULL);
  const char* symname = (sym && sym->name) ? sym->name : "[NULL]";
  const char* symalias = (sym && sym->alias) ? sym->alias : "[NULL]";
  printf("Relocation failed for relocation %p, symbol %p: name = '%s', alias = '%s'\n",
    reloc, sym, symname, symalias);
}

require_noerr(rval, finish);

両方の関数を変更し、カーネルを構築して起動し、kext をロードしてみてください。これにより、何か作業ができるようになることを願っています。乗り方を教えてください!

現在、問題を再現する方法がないため、上記のコードをテストしていないことに注意してください。

于 2013-02-28T21:13:20.523 に答える