在研究C代碼的拆卸時,這讓我感到震驚。通常,在保存幀指針之後的函數組裝中,我們推送被保存的寄存器並在返回之前將其恢復。 x86 ABI告訴我們哪些寄存器是被調用者/調用者保存的。然而,當我看到編譯器在組裝這些函數時行爲不同時,我的問題就開始了。例如:x86彙編中的序言和推送被調用者保存寄存器
Case 1
(gdb) disassemble EVP_CipherInit_ex
Dump of assembler code for function EVP_CipherInit_ex:
0xb1258044 <+0>: push %ebp
0xb1258045 <+1>: mov %esp,%ebp
0xb1258047 <+3>: push %edi
0xb1258048 <+4>: push %esi
0xb1258049 <+5>: push %ebx
Case 2
(gdb) disassemble FIPS_mode
Dump of assembler code for function FIPS_mode:
0xb12614c4 <+0>: push %ebp
0xb12614c5 <+1>: mov %esp,%ebp
0xb12614c7 <+3>: push %ebx
0xb12614c8 <+4>: sub $0x4,%esp
Case 3
(gdb) disassemble OPENSSL_init
Dump of assembler code for function OPENSSL_init:
0xb124fae4 <+0>: push %ebp
0xb124fae5 <+1>: mov %esp,%ebp
0xb124fae7 <+3>: push %ebx
0xb124fae8 <+4>: sub $0x4,%esp
Case 4
(gdb) disassemble FIPS_module_mode
Dump of assembler code for function FIPS_module_mode:
0xb117dfdc <+0>: push %edi
0xb117dfdd <+1>: push %esi
0xb117dfde <+2>: push %ebx
0xb117dfdf <+3>: sub $0x10,%esp
Q1。在前三種情況下,我們保存了幀指針ebp,以及另一個常用寄存器ebx但其餘部分不同。編譯器如何識別要推送哪些文件以及要避免哪些文件?這是一種優化遊戲嗎?任何關於此的指針都會非常有幫助。 Q2302。在拆卸FIPS_module_mode我們甚至沒有保存幀指針ebp。我知道我們可以通過使用編譯器選項優化來節省空間。我的興趣在於理解這種幀指針部分的缺失是由於顯式編譯器優化還是由於某些其他參數有助於決定這一點。
Q3。像gdb這樣的調試器如何在特定的函數中檢測到情況4,在覈心轉儲中省略了幀指針?
的張貼的函數的原型:
int FIPS_module_mode(void);
void OPENSSL_init(void);
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
ENGINE *impl, const unsigned char *key,
const unsigned char *iv, int enc);
int FIPS_mode(void);
這上NetBSD5運行和信息轉儲由GDB
我們可以看到C嗎?特別是,啓用優化時,靜態函數可能會忽略ABI。 –
也許還需要知道該平臺 - gdb暗示linux,但可能是mingw,而windows和linux調用約定不同 –
@Jon Chesterfield - 所討論的函數都不是靜態的 –