如果你有看之前的 c++ runtime - global object ctor
(0),
(1) 應該知道 g++ 會為 global object constructor 準備一個 _GLOBALxxx 的 function。只要 call 它, 就會完成所有 global object ctor 的呼叫。
g++ 4.4, g++ 4.6 將 _GLOBAL__sub_I_ab 放在 .ctor section
g++ 4.7 將 _GLOBAL__sub_I_ab 放在 .init_array section
運用類似 init bss 的技巧, 我們在 linker script (cpp.ld) 插入 symbol, L12 ~ L24, 只要其中一段就可以, 不過我為了支援 g++ 4.4, g++4.6, g++ 4.7 所以補了兩段。
但是我不知道 g++ 4.7.1 的 _GLOBAL__sub_I_ab 放在那個 section, 無法使用 L21 的指令, 只好用 L13 ~ L17 這樣有點遜的方法來處理。
110 # call global object ctor
111 init_cpp_global_asm:
112 #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 7
113 mov $__end_global_ctor__, %edi /* Destination */
114 mov $__start_global_ctor__, %esi /* Source */
115 #else
116 mov $__end_ctors, %edi /* Destination */
117 mov $__start_ctors, %esi /* Source */
118 #endif
119 jmp 2f
120 1:
121 mov %esi, %ebx
122 calll *(%ebx)
123 add $4, %esi
124 2:
125 cmp %edi, %esi
126 jne 1b
127 ret
init_cpp_global_asm 依序呼叫 linker script symbol
__end_global_ctor__,
__start_global_ctor__ 之間的位址, 不過在這例子中:
00000944 A __end_global_ctor__
00000940 T __start_global_ctor__
所以只有一個 4byte 位址, 4e 04 00 00 => 0x0000044e (_GLOBAL__sub_I_ab),
如果你忘記這怎麼來的請參考:
c++ runtime - global object ctor (0)
122 calll *(%ebx)
呼叫它就對了。at &t call 指令語法很奇怪, 別擔心, 常看就會習慣了。
寫成下面的程式碼也可以:
121 mov $__start_global_ctor__, %ebx
122 calll *(%ebx)
這樣應該比較好懂, 沒有惱人的 loop, 不過你得知道這樣會有什麼風險, 能看懂這篇的朋友我相信應該有能力處理這小問題。也應該換你們踩踩地雷, 保證印象深刻。
82 calll init_cpp_global_asm
83 calll cpp_main
最後在 c++ main 之前呼叫 init_cpp_global_asm (cpp_main) 就完成 global object constructor 的呼叫。global object constructor 的秘密到此結束, 再來我會談談 global object destructor。
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。