2012-08-11 4 views
10

अगर मैं निम्नलिखित ऑब्जेक्टिव-सी स्रोत फ़ाइल प्राप्त करें:उद्देश्य-सी रनटाइम कक्षाओं और विधियों की सूची कैसे प्राप्त करता है?

// test.m 
#import <objc/Object.h> 

@interface MySuperClass: Object { 

} 
-(void) myMessage1; 
@end 

@implementation MySuperClass 
-(void) myMessage1 { 

} 
@end 

@interface MyClass: MySuperClass { 

} 
-(void) myMessage2; 
@end 

@implementation MyClass 
-(void) myMessage2 { 

} 
@end 

int main() { 

    return 0; 
} 

और clang -fobjc-nonfragile-abi -fnext-runtime -S test.m साथ इसे से एक विधानसभा फ़ाइल जनरेट करने का प्रयास है, मैं करने के निम्नलिखित विधानसभा कोड:

.file "test.m" 
    .text 
    .align 16, 0x90 
    .type _2D__5B_MySuperClass_20_myMessage1_5D_,@function 
_2D__5B_MySuperClass_20_myMessage1_5D_: # @"\01-[MySuperClass myMessage1]" 
.Ltmp0: 
    .cfi_startproc 
# BB#0: 
    movq %rdi, -8(%rsp) 
    movq %rsi, -16(%rsp) 
    ret 
.Ltmp1: 
    .size _2D__5B_MySuperClass_20_myMessage1_5D_, .Ltmp1-_2D__5B_MySuperClass_20_myMessage1_5D_ 
.Ltmp2: 
    .cfi_endproc 
.Leh_func_end0: 

    .align 16, 0x90 
    .type _2D__5B_MyClass_20_myMessage2_5D_,@function 
_2D__5B_MyClass_20_myMessage2_5D_:  # @"\01-[MyClass myMessage2]" 
.Ltmp3: 
    .cfi_startproc 
# BB#0: 
    movq %rdi, -8(%rsp) 
    movq %rsi, -16(%rsp) 
    ret 
.Ltmp4: 
    .size _2D__5B_MyClass_20_myMessage2_5D_, .Ltmp4-_2D__5B_MyClass_20_myMessage2_5D_ 
.Ltmp5: 
    .cfi_endproc 
.Leh_func_end1: 

    .globl main 
    .align 16, 0x90 
    .type main,@function 
main:         # @main 
.Ltmp6: 
    .cfi_startproc 
# BB#0: 
    movl $0, %eax 
    movl $0, -4(%rsp) 
    ret 
.Ltmp7: 
    .size main, .Ltmp7-main 
.Ltmp8: 
    .cfi_endproc 
.Leh_func_end2: 

    .type L_OBJC_CLASS_NAME_,@object # @"\01L_OBJC_CLASS_NAME_" 
    .section "__TEXT,__objc_classname,cstring_literals","aw",@progbits 
L_OBJC_CLASS_NAME_: 
    .asciz "MySuperClass" 
    .size L_OBJC_CLASS_NAME_, 13 

    .type l_OBJC_METACLASS_RO_$_MySuperClass,@object # @"\01l_OBJC_METACLASS_RO_$_MySuperClass" 
    .section "__DATA, __objc_const","aw",@progbits 
    .align 8 
l_OBJC_METACLASS_RO_$_MySuperClass: 
    .long 1      # 0x1 
    .long 40      # 0x28 
    .long 40      # 0x28 
    .zero 4 
    .quad 0 
    .quad L_OBJC_CLASS_NAME_ 
    .quad 0 
    .quad 0 
    .quad 0 
    .quad 0 
    .quad 0 
    .size l_OBJC_METACLASS_RO_$_MySuperClass, 72 

    .type OBJC_METACLASS_$_MySuperClass,@object # @"OBJC_METACLASS_$_MySuperClass" 
    .section "__DATA, __objc_data","aw",@progbits 
    .globl OBJC_METACLASS_$_MySuperClass 
    .align 8 
OBJC_METACLASS_$_MySuperClass: 
    .quad OBJC_METACLASS_$_Object 
    .quad OBJC_METACLASS_$_Object 
    .quad _objc_empty_cache 
    .quad _objc_empty_vtable 
    .quad l_OBJC_METACLASS_RO_$_MySuperClass 
    .size OBJC_METACLASS_$_MySuperClass, 40 

    .type L_OBJC_METH_VAR_NAME_,@object # @"\01L_OBJC_METH_VAR_NAME_" 
    .section "__TEXT,__objc_methname,cstring_literals","aw",@progbits 
L_OBJC_METH_VAR_NAME_: 
    .asciz "myMessage1" 
    .size L_OBJC_METH_VAR_NAME_, 11 

    .type L_OBJC_METH_VAR_TYPE_,@object # @"\01L_OBJC_METH_VAR_TYPE_" 
    .section "__TEXT,__objc_methtype,cstring_literals","aw",@progbits 
L_OBJC_METH_VAR_TYPE_: 
    .asciz "[email protected]:8" 
    .size L_OBJC_METH_VAR_TYPE_, 8 

    .type l_OBJC_$_INSTANCE_METHODS_MySuperClass,@object # @"\01l_OBJC_$_INSTANCE_METHODS_MySuperClass" 
    .section "__DATA, __objc_const","aw",@progbits 
    .align 8 
l_OBJC_$_INSTANCE_METHODS_MySuperClass: 
    .long 24      # 0x18 
    .long 1      # 0x1 
    .quad L_OBJC_METH_VAR_NAME_ 
    .quad L_OBJC_METH_VAR_TYPE_ 
    .quad _2D__5B_MySuperClass_20_myMessage1_5D_ 
    .size l_OBJC_$_INSTANCE_METHODS_MySuperClass, 32 

    .type l_OBJC_CLASS_RO_$_MySuperClass,@object # @"\01l_OBJC_CLASS_RO_$_MySuperClass" 
    .align 8 
l_OBJC_CLASS_RO_$_MySuperClass: 
    .long 0      # 0x0 
    .long 8      # 0x8 
    .long 8      # 0x8 
    .zero 4 
    .quad 0 
    .quad L_OBJC_CLASS_NAME_ 
    .quad l_OBJC_$_INSTANCE_METHODS_MySuperClass 
    .quad 0 
    .quad 0 
    .quad 0 
    .quad 0 
    .size l_OBJC_CLASS_RO_$_MySuperClass, 72 

    .type OBJC_CLASS_$_MySuperClass,@object # @"OBJC_CLASS_$_MySuperClass" 
    .section "__DATA, __objc_data","aw",@progbits 
    .globl OBJC_CLASS_$_MySuperClass 
    .align 8 
OBJC_CLASS_$_MySuperClass: 
    .quad OBJC_METACLASS_$_MySuperClass 
    .quad OBJC_CLASS_$_Object 
    .quad _objc_empty_cache 
    .quad _objc_empty_vtable 
    .quad l_OBJC_CLASS_RO_$_MySuperClass 
    .size OBJC_CLASS_$_MySuperClass, 40 

    .type L_OBJC_CLASS_NAME_1,@object # @"\01L_OBJC_CLASS_NAME_1" 
    .section "__TEXT,__objc_classname,cstring_literals","aw",@progbits 
L_OBJC_CLASS_NAME_1: 
    .asciz "MyClass" 
    .size L_OBJC_CLASS_NAME_1, 8 

    .type l_OBJC_METACLASS_RO_$_MyClass,@object # @"\01l_OBJC_METACLASS_RO_$_MyClass" 
    .section "__DATA, __objc_const","aw",@progbits 
    .align 8 
l_OBJC_METACLASS_RO_$_MyClass: 
    .long 1      # 0x1 
    .long 40      # 0x28 
    .long 40      # 0x28 
    .zero 4 
    .quad 0 
    .quad L_OBJC_CLASS_NAME_1 
    .quad 0 
    .quad 0 
    .quad 0 
    .quad 0 
    .quad 0 
    .size l_OBJC_METACLASS_RO_$_MyClass, 72 

    .type OBJC_METACLASS_$_MyClass,@object # @"OBJC_METACLASS_$_MyClass" 
    .section "__DATA, __objc_data","aw",@progbits 
    .globl OBJC_METACLASS_$_MyClass 
    .align 8 
OBJC_METACLASS_$_MyClass: 
    .quad OBJC_METACLASS_$_Object 
    .quad OBJC_METACLASS_$_MySuperClass 
    .quad _objc_empty_cache 
    .quad _objc_empty_vtable 
    .quad l_OBJC_METACLASS_RO_$_MyClass 
    .size OBJC_METACLASS_$_MyClass, 40 

    .type L_OBJC_METH_VAR_NAME_2,@object # @"\01L_OBJC_METH_VAR_NAME_2" 
    .section "__TEXT,__objc_methname,cstring_literals","aw",@progbits 
L_OBJC_METH_VAR_NAME_2: 
    .asciz "myMessage2" 
    .size L_OBJC_METH_VAR_NAME_2, 11 

    .type l_OBJC_$_INSTANCE_METHODS_MyClass,@object # @"\01l_OBJC_$_INSTANCE_METHODS_MyClass" 
    .section "__DATA, __objc_const","aw",@progbits 
    .align 8 
l_OBJC_$_INSTANCE_METHODS_MyClass: 
    .long 24      # 0x18 
    .long 1      # 0x1 
    .quad L_OBJC_METH_VAR_NAME_2 
    .quad L_OBJC_METH_VAR_TYPE_ 
    .quad _2D__5B_MyClass_20_myMessage2_5D_ 
    .size l_OBJC_$_INSTANCE_METHODS_MyClass, 32 

    .type l_OBJC_CLASS_RO_$_MyClass,@object # @"\01l_OBJC_CLASS_RO_$_MyClass" 
    .align 8 
l_OBJC_CLASS_RO_$_MyClass: 
    .long 0      # 0x0 
    .long 8      # 0x8 
    .long 8      # 0x8 
    .zero 4 
    .quad 0 
    .quad L_OBJC_CLASS_NAME_1 
    .quad l_OBJC_$_INSTANCE_METHODS_MyClass 
    .quad 0 
    .quad 0 
    .quad 0 
    .quad 0 
    .size l_OBJC_CLASS_RO_$_MyClass, 72 

    .type OBJC_CLASS_$_MyClass,@object # @"OBJC_CLASS_$_MyClass" 
    .section "__DATA, __objc_data","aw",@progbits 
    .globl OBJC_CLASS_$_MyClass 
    .align 8 
OBJC_CLASS_$_MyClass: 
    .quad OBJC_METACLASS_$_MyClass 
    .quad OBJC_CLASS_$_MySuperClass 
    .quad _objc_empty_cache 
    .quad _objc_empty_vtable 
    .quad l_OBJC_CLASS_RO_$_MyClass 
    .size OBJC_CLASS_$_MyClass, 40 

    .type L_OBJC_LABEL_CLASS_$,@object # @"\01L_OBJC_LABEL_CLASS_$" 
    .section "__DATA, __objc_classlist, regular, no_dead_strip","aw",@progbits 
    .align 8 
L_OBJC_LABEL_CLASS_$: 
    .quad OBJC_CLASS_$_MySuperClass 
    .quad OBJC_CLASS_$_MyClass 
    .size L_OBJC_LABEL_CLASS_$, 16 

    .type L_OBJC_IMAGE_INFO,@object # @"\01L_OBJC_IMAGE_INFO" 
    .section "__DATA, __objc_imageinfo, regular, no_dead_strip","a",@progbits 
    .align 4 
L_OBJC_IMAGE_INFO: 
    .long 0      # 0x0 
    .long 16      # 0x10 
    .size L_OBJC_IMAGE_INFO, 8 


    .section ".note.GNU-stack","",@progbits 

मेरे सवाल यह है: उद्देश्य-सी रनटाइम लाइब्रेरी, जिसे test.o के विरुद्ध लिंक किया जाना चाहिए ताकि निष्पादन योग्य फ़ाइल सफलतापूर्वक बनाई जा सके, उदाहरण के लिए, एक vtable बनाने के लिए विधियों की सूची पुनर्प्राप्त करें? क्या कम से कम समय पर इस जानकारी को प्राप्त करने के लिए .section ..., @function, .section ..., @object या .section ..., @progbits असेंबली निर्देशों का उपयोग करना संभव है?

+0

मुझे पता चला कि 'L_OBJC_LABEL_CLASS_ $' लेबल (असेंबली फ़ाइल के अंत में) सरणी में सभी लागू क्लास पतों की एक सूची के बाद है। यह उपयोगी हो सकता है ... – LuisABOL

उत्तर

20

कंपाइलर, लिंकर और रनटाइम एक साथ काम करते हैं।

पहले, संकलक प्रत्येक वर्ग के लिए स्रोत कोड पार्स करके वर्ग के उदाहरण चर, गुण, चयनकर्ताओं, और विधियों का वर्णन .long, .zero, और .quad तरह निर्देशों का उत्सर्जन करता है। असेंबलर इन निर्देशों को कच्चे डेटा में बदल देता है।

डेटा उस प्रारूप में है जो रनटाइम समझता है। उदाहरण के लिए, प्रतीक OBJC_CLASS_$_MyClass पर शुरू होने वाला डेटा रनटाइम के struct class_t (objc-runtime-new.h में परिभाषित) के लेआउट से मेल खाता है। प्रतीक l_OBJC_CLASS_RO_$_MyClass पर डेटा रनटाइम के struct class_ro_t के लेआउट से मेल खाता है (हालांकि अधिकांश फ़ील्ड 0 हैं क्योंकि रनटाइम उन्हें कक्षा लोड करते समय अपडेट करता है)। struct class_ro_t में baseMethods प्रकार method_list_t * का क्षेत्र है, जो l_OBJC_CLASS_RO_$_MyClass के मामले में l_OBJC_$_INSTANCE_METHODS_MyClass पर प्रारंभ किया गया है। l_OBJC_$_INSTANCE_METHODS_MyClass पर आपको struct method_list_t की तरह डेटा मिलेगा, जो कक्षा में प्रत्येक विधि के लिए struct method_t की एक सरणी के साथ समाप्त होता है। आपके उदाहरण में, यह बहुत रोचक नहीं है क्योंकि आपके प्रत्येक वर्ग में केवल एक ही विधि है।

कंपाइलर .section निर्देशों का उपयोग करता है ताकि लिंकर को यह बताने के लिए कि उस डेटा के समूह को एक साथ कैसे समूहित किया जाए। उदाहरण के लिए, भागों के सभी __objc_classlist नामक अनुभाग में एक साथ रखे जाएंगे। इस तरह, रनटाइम सिर्फ __objc_classlist नामक अनुभाग को देख सकता है, और उसके बाद पूरे अनुभाग को struct class_t की सरणी के रूप में संसाधित कर सकता है। में GETSECT मैक्रो पर एक नज़र डालें।

लिंकर समारोह _objc_init (objc-os.mm में) के लिए व्यवस्था को चलाने के लिए बहुत अपनी प्रक्रिया के जीवनकाल के शुरू में, main से पहले। _objc_init फ़ंक्शन गतिशील लोडर के साथ कुछ कॉलबैक पंजीकृत करता है। विशेष रूप से, यह लोडर को map_images (objc-runtime-new.mm में) पर कॉल करने के लिए कहता है, जो map_images_nolock पर कॉल करता है, जो अंततः _read_images पर कॉल करता है। _read_images फ़ंक्शन वास्तव में कंपाइलर द्वारा उत्सर्जित डेटा के उन हिस्सों को पार करता है और उन्हें डेटा संरचनाओं में बदल देता है जो objc_msgSend वास्तव में वस्तुओं को संदेश भेजने के लिए उपयोग करता है।

You can download an archive of the Mac OS X 10.8 Objective-C runtime source code और जानने के लिए। इस संग्रह में आईओएस/एआरएम (और यहां तक ​​कि विंडोज़!) के लिए स्रोत फाइलें भी शामिल हैं, हालांकि यह आईओएस के किसी भी संस्करण में बिल्कुल से मेल नहीं खाती है।

+1

बहुत अच्छा, आदमी! यही वही है जो मैं जानना चाहता था। आपका बहुत बहुत धन्यवाद! – LuisABOL

0

ऐसा नहीं है कि रनटाइम जानता है कि अपने प्रोग्राम को कैसे पढ़ा जाए, लेकिन ओबीजेसी फ्रंट-एंड रनटाइम का उपयोग करने के लिए कोड बेस का अनुवाद करता है।

+0

हाँ, आप सही हैं, लेकिन उपरोक्त असेंबली कोड उद्देश्य-सी रनटाइम (मुझे लगता है) का उपयोग करने के लिए कंपाइलर द्वारा उत्पन्न किया गया है। इसे उद्देश्य-सी रनटाइम ('objc_msgSend_fixup',' _objc_empty_cache' और '_objc_empty_vtable') के प्रतीक के प्रतीक हैं, उदाहरण के लिए। लेकिन उदाहरण के लिए, 'objc_msgSend_fixup' फ़ंक्शन, कक्षाओं के तरीकों को प्राप्त करने की आवश्यकता है और मुझे लगता है कि यह निष्पादन योग्य फ़ाइल के एक विशिष्ट अनुभाग को पढ़कर किया जाता है। तो, मैं जानना चाहता हूं कि यह कौन सा अनुभाग है और यह कैसे किया जाता है। – LuisABOL

संबंधित मुद्दे