一個有趣的學術問題,我試圖解決:功能的設置,標誌C函數總是使用符號存根的,而不是直接調用
在C代碼,我想在運行時動態重新綁定符號,就像Facebook's fishhook repo這重新綁定函數符號。我主要關心Mach-O可執行文件的__DATA.__la_symbol_ptr
部分中引用的符號。隨着魚鉤的實現,你提供了你的新函數來替換原來的函數,一個字符串指出你想要替換的函數,還有一個全局函數指針,它可以取代原來的被替換的函數。
例如,從魚鉤回購自述採取...
static int (*orig_close)(int);
int my_close(int fd) {
return orig_close(fd);
}
...然後在main
rebind_symbols((struct rebinding[1]){{"close", my_close, (void *)&orig_close}}, 1);
這是真棒,但我希望能夠完全切換撥打my_close
的所有電話,並撥打close
,反之亦然。例如,而不是指向原始close
全局函數指針的,我想我的實現看起來像這樣:
int my_close(int fd) {
return my_close(fd);
}
不幸的是,因爲這個符號在同一模塊中引用,這個符號將得到通過直接呼叫而不是符號存根調用。從main
0x100001e00 <+0>: push rbp
0x100001e01 <+1>: mov rbp, rsp
0x100001e04 <+4>: sub rsp, 0x20
0x100001e08 <+8>: xor eax, eax
0x100001e0a <+10>: mov dword ptr [rbp - 0x4], 0x0
0x100001e11 <+17>: mov dword ptr [rbp - 0x8], edi
0x100001e14 <+20>: mov qword ptr [rbp - 0x10], rsi
0x100001e18 <+24>: mov edi, eax
0x100001e1a <+26>: call 0x100001da0 ; my_close at main.m:42
0x100001e1f <+31>: xor edi, edi
0x100001e21 <+33>: mov dword ptr [rbp - 0x14], eax
0x100001e24 <+36>: mov eax, edi
0x100001e26 <+38>: add rsp, 0x20
0x100001e2a <+42>: pop rbp
0x100001e2b <+43>: ret
好了,很容易的修復調用這個函數的時候,這裏的集會,我可以用匯編指令來標記的功能較弱,使用weakref關閉編譯了一個潛在的堆棧溢出。更改my_close
到:
static int f(int) __attribute__ ((weakref ("my_close")));
__attribute__((weak))
int my_close(int fd) {
return f(fd);
}
然後將產生以下組件main
:
0x100001df0 <+0>: push rbp
0x100001df1 <+1>: mov rbp, rsp
0x100001df4 <+4>: sub rsp, 0x20
0x100001df8 <+8>: xor eax, eax
0x100001dfa <+10>: mov dword ptr [rbp - 0x4], 0x0
0x100001e01 <+17>: mov dword ptr [rbp - 0x8], edi
0x100001e04 <+20>: mov qword ptr [rbp - 0x10], rsi
0x100001e08 <+24>: mov edi, eax
0x100001e0a <+26>: call 0x100001e5e ; symbol stub for: my_close
0x100001e0f <+31>: xor edi, edi
0x100001e11 <+33>: mov dword ptr [rbp - 0x14], eax
0x100001e14 <+36>: mov eax, edi
0x100001e16 <+38>: add rsp, 0x20
0x100001e1a <+42>: pop rbp
0x100001e1b <+43>: ret
因此,這裏是我堅持的部分:引用my_close
內my_close
的時候,它總是導致直接調用。例如:這裏是爲my_close
0x100001dd0 <+0>: push rbp
0x100001dd1 <+1>: mov rbp, rsp
0x100001dd4 <+4>: sub rsp, 0x10
0x100001dd8 <+8>: mov dword ptr [rbp - 0x4], edi
0x100001ddb <+11>: mov edi, dword ptr [rbp - 0x4]
0x100001dde <+14>: call 0x100001dd0 ; <+0> at main.m:44
0x100001de3 <+19>: add rsp, 0x10
0x100001de7 <+23>: pop rbp
0x100001de8 <+24>: ret
的組件有任何彙編指令,我可以使用(我已經錯過了)告訴my_close
被視爲存根被稱爲內my_close
什麼時候?是的,我知道我可以使用dlsym
來獲得原版,但我很固執:]
回想一下'weakref'' __attribute__'似乎無法工作,因爲函數需要聲明爲靜態。我會留下這個問題。 –
只是一個想法......爲什麼不把'my_call'聲明爲一個全局函數指針類型(甚至可能使用'volatile'屬性,並且最好確保它是原子性和對齊的),所以對符號的每一個引用實際上是對全局變量(你可以隨時更新)....? – Myst
對於您可能感興趣的替代路由:https://stackoverflow.com/a/34120249/5329717 –