[英]How do I get a function name in the symbol table to point to a different function?
在 MacOS Ventura 上,使用 dlopen(NULL, 0) 獲取動態加載程序的句柄會返回包含整個可執行文件符號表的句柄。 使用這個句柄,可以獲得指向符號數據的指針,訪問和修改它們的內容,這些更改將滲透到整個程序中。 但是,嘗試使用函數指針進行此操作的方式不同。
例如,下面的代碼:
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
int my_var = 0;
int main() {
void *handle = dlopen(NULL, 0);
int *a = dlsym(handle, "my_var");
*a = 5;
printf("%d", my_var);
return 0;
}
將打印 5 而不是 0。但是,當嘗試使用 function 指針進行類似操作時:
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
typedef void (*ftype)(void);
void fun1() {
printf("a");
}
void fun2() {
printf("b");
}
int main() {
void *handle = dlopen(NULL, 0);
ftype f1ptr;
*(void **)(&f1ptr) = dlsym(handle, "fun1");
f1ptr = fun2;
fun1();
return 0;
}
將打印 a 而不是 b。 有沒有辦法用 function 指針執行類似於第一個代碼段的操作? 本質上,我希望 fun1 現在指向 fun2 指向的代碼。 將 f1ptr 的類型交換為“ftype *”然后執行“*f1ptr = fun2”會導致總線故障。
但是,嘗試使用函數指針進行此操作的方式不同。
標識符命名為 object 或 function。function 的標識符不是 function 指針,並且您的示例未顯示代碼對對象或函數的工作方式不同。
In int *a = dlsym(handle, "my_var");
,您的代碼獲得指向my_var
的指針。 然后它使用*a = 5;
更改my_var
的值。
在*(void **)(&f1ptr) = dlsym(handle, "fun1");
,您的代碼獲得了指向fun1
的指針(盡管它處理不當,如下所述)。 所以f1ptr
是指向fun1
的指針。 它是指向 function 的指針,而不是指向 function 的指針。 如果函數可以某種方式修改,那么*f1ptr = …;
將修改 function。
但是,您不使用*f1ptr = …;
. 你使用f1ptr = fun2;
. 這只是改變f1ptr
。 它不會改變f1ptr
指向的內容。 它不會改變fun1
。
fun1
是 function 的標識符。它不是指針。 所以沒有指向改變的指針。 程序中無法使fun1
成為不同的 function 或指向不同的 function。
關於為什么*(void **)(&f1ptr) = dlsym(handle, "fun1");
是錯誤的,這表示獲取f1ptr
的地址,將地址轉換為void **
,並使用該 memory 位置,就好像它是void *
一樣。 然后為 memory 位置分配dlsym
返回的void *
的值。 換句話說,您正在使用指向void
的類型指針訪問指向函數 object f1ptr
的指針。 這違反了 C 2018 6.5 7,它說 object 只能使用其定義的類型或某些其他類型進行訪問,其中任何一種都不允許使用void *
訪問指向 function 的指針。
C 標准允許指向 function 的指針和指向void
的指針在 memory 中具有不同的表示形式,甚至不同的大小,在這種情況下,此分配將“機械地”失敗; 寫入f1ptr
的字節不適合用作指向函數的指針。 但即使在所有指針都具有相同表示的 C 實現中,此賦值也可能與編譯器的優化發生沖突。 它不應該被使用。
將dlsym
的結果分配給f1ptr
的正確方法是將結果轉換為必要的類型:
f1ptr = (ftype) dlsym(handle, "fun1");
(這仍然不會讓您更改fun1
;它只是向您展示如何正確使用dlsym
。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.