私はObjective-Cランタイムをいじり、Objective-Cコードをリンクせずにコンパイルしようとしてlibobjc
います.プログラムにセグメンテーション違反の問題があるため、そこからアセンブリファイルを生成しました. アセンブリ ファイル全体を表示する必要はないと思います。関数のある時点でmain
、次の行を取得しました (ちなみに、これは、seg fault が発生した後の行です)。
callq *l_objc_msgSend_fixup_alloc
の定義は次のl_objc_msgSend_fixup_alloc
とおりです。
.hidden l_objc_msgSend_fixup_alloc # @"\01l_objc_msgSend_fixup_alloc"
.type l_objc_msgSend_fixup_alloc,@object
.section "__DATA, __objc_msgrefs, coalesced","aw",@progbits
.weak l_objc_msgSend_fixup_alloc
.align 16
l_objc_msgSend_fixup_alloc:
.quad objc_msgSend_fixup
.quad L_OBJC_METH_VAR_NAME_
.size l_objc_msgSend_fixup_alloc, 16
(何が起こるかを見るためだけに) を返すobjc_msgSend_fixup
関数 ( ) として再実装しましたが、この関数は呼び出されていません (呼び出す前にプログラムがクラッシュします)。id objc_msgSend_fixup(id self, SEL op, ...)
nil
それで、私の質問は、何をcallq *l_objc_msgSend_fixup_alloc
することになっていて、objc_msgSend_fixup
(の後にl_objc_msgSend_fixup_alloc:
)あるべきこと(関数またはオブジェクト)ですか?
編集
わかりやすく説明すると、ソース ファイルを objc ライブラリにリンクしていません。私がやろうとしているのは、ライブラリの一部を実装して、それがどのように機能するかを確認することです。これが私がやったことのアプローチです:
#include <stdio.h>
#include <objc/runtime.h>
@interface MyClass {
}
+(id) alloc;
@end
@implementation MyClass
+(id) alloc {
// alloc the object
return nil;
}
@end
id objc_msgSend_fixup(id self, SEL op, ...) {
printf("Calling objc_msgSend_fixup()...\n");
// looks for the method implementation for SEL in self's method list
return nil; // Since this is just a test, this function doesn't need to do that
}
int main(int argc, char *argv[]) {
MyClass *m;
m = [MyClass alloc]; // At this point, according to the assembly code generated
// objc_msgSend_fixup should be called. So, the program should, at least, print
// "Calling objc_msgSend_fixup()..." on the screen, but it crashes before
// objc_msgSend_fixup() is called...
return 0;
}
ランタイムがオブジェクトの vtable またはオブジェクトのクラスのメソッド リストにアクセスして、呼び出す正しいメソッドを見つける必要がある場合、実際にこれを行う関数は何ですか? objc_msgSend_fixup
この場合は だと思います。したがって、objc_msgSend_fixup
が呼び出されると、パラメータの 1 つとしてオブジェクトを受け取り、このオブジェクトが初期化されていない場合、関数は失敗します。
そこで、独自のバージョンの を実装しましたobjc_msgSend_fixup
。上記のアセンブリ ソースによると、それを呼び出す必要があります。関数がパラメーターとして渡されたセレクターの実装を実際に探しているかどうかは問題ではありません。objc_msgSend_lookup
呼ばれたいだけ。しかし、それは呼び出されていません。つまり、オブジェクトのデータを検索する関数は、呼び出されてエラーを引き起こすのではなく、呼び出されてnil
いません (それは a を返すためです (ちなみに、これは問題ではありません))。 . プログラムセグメントが呼び出される前に失敗しますobjc_msgSend_lookup
...
編集 2
より完全なアセンブリ スニペット:
.globl main
.align 16, 0x90
.type main,@function
main: # @main
.Ltmp20:
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp21:
.cfi_def_cfa_offset 16
.Ltmp22:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp23:
.cfi_def_cfa_register %rbp
subq $32, %rsp
movl $0, %eax
leaq l_objc_msgSend_fixup_alloc, %rcx
movl $0, -4(%rbp)
movl %edi, -8(%rbp)
movq %rsi, -16(%rbp)
movq L_OBJC_CLASSLIST_REFERENCES_$_, %rsi
movq %rsi, %rdi
movq %rcx, %rsi
movl %eax, -28(%rbp) # 4-byte Spill
callq *l_objc_msgSend_fixup_alloc
movq %rax, -24(%rbp)
movl -28(%rbp), %eax # 4-byte Reload
addq $32, %rsp
popq %rbp
ret
についてl_objc_msgSend_fixup_alloc
は、次のとおりです。
.hidden l_objc_msgSend_fixup_alloc # @"\01l_objc_msgSend_fixup_alloc"
.type l_objc_msgSend_fixup_alloc,@object
.section "__DATA, __objc_msgrefs, coalesced","aw",@progbits
.weak l_objc_msgSend_fixup_alloc
.align 16
l_objc_msgSend_fixup_alloc:
.quad objc_msgSend_fixup
.quad L_OBJC_METH_VAR_NAME_
.size l_objc_msgSend_fixup_alloc, 16
の場合L_OBJC_CLASSLIST_REFERENCES_$_
:
.type L_OBJC_CLASSLIST_REFERENCES_$_,@object # @"\01L_OBJC_CLASSLIST_REFERENCES_$_"
.section "__DATA, __objc_classrefs, regular, no_dead_strip","aw",@progbits
.align 8
L_OBJC_CLASSLIST_REFERENCES_$_:
.quad OBJC_CLASS_$_MyClass
.size L_OBJC_CLASSLIST_REFERENCES_$_, 8
OBJC_CLASS_$_MyClass
MyClass
これもコンパイラによって生成された構造体定義へのポインターであり、アセンブリ コードにも存在します。