Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
映射库函数赋值的间接指针-C-OSX_C_Macos_Assembly_Dynamic Library_Mach O - Fatal编程技术网

映射库函数赋值的间接指针-C-OSX

映射库函数赋值的间接指针-C-OSX,c,macos,assembly,dynamic-library,mach-o,C,Macos,Assembly,Dynamic Library,Mach O,给出以下简单代码段: int main (void) { void* foo = scanf; void* bar = sscanf; } 以下是反汇编(取自mach-o可执行文件): 非惰性符号指针的一小部分: 符号表的一小部分: 我似乎不理解可执行文件中的第5行和第6行(scanf&sscanf到rax/rcx的movq)。 foo和bar(最终)如何分别拥有scanf和sscanf的地址。 我认为这与映射到进程的动态库(以及最有可能指向该进程的非惰性符号指针)有关

给出以下简单代码段:

int main (void) {
    void* foo =  scanf;
    void* bar = sscanf;
}
以下是反汇编(取自mach-o可执行文件):

非惰性符号指针的一小部分:

符号表的一小部分:

我似乎不理解可执行文件中的第5行和第6行(scanf&sscanf到rax/rcx的movq)。 foo和bar(最终)如何分别拥有scanf和sscanf的地址。 我认为这与映射到进程的动态库(以及最有可能指向该进程的非惰性符号指针)有关,但我不明白是如何做到的

谢谢,动态链接器负责绑定符号。要查看发生了什么,首先使用
-fno pie
选项编译测试项目,以禁用位置独立的可执行文件。这样,您在MachOView中看到的偏移量在运行时将是相同的。然后启动可执行文件,将
DYLD\u PRINT\u绑定
环境变量设置为
YES
。结果如下:

$ DYLD_PRINT_BINDINGS=YES ./a.out 
dyld: bind: a.out:0x100001010 = libsystem_c.dylib:_scanf, *0x100001010 = 0x7FFF94578017
dyld: bind: a.out:0x100001018 = libsystem_c.dylib:_sscanf, *0x100001018 = 0x7FFF94578707
...

生成的代码从非惰性符号指针加载
scanf
的地址。那里没有什么特别的。当dyld加载可执行文件时,它“绑定”每个非惰性符号指针,将其值设置为符号的正确地址

非惰性符号指针用于以下引用:(1)指向不同库中的内容,(2)是数据引用,而不是对函数的调用。在您的示例中,您没有直接调用
scanf
,因此它是一个数据引用,而
scanf
不在可执行文件中,因此它是对不同库的引用

同一可执行文件中的引用使用了固定的PC相对偏移量:编译器和链接器知道代码和数据将相邻加载,因此它们可以在构建时选择偏移量。函数调用的引用是惰性的:在运行时,对函数的第一个调用通过dyld first路由,dyld first查找符号并绑定惰性符号指针以供将来调用


正如0xced所指出的,您可以设置环境变量
DYLD\u PRINT\u绑定
来监视DYLD的工作。dyld手册页描述了可以设置的其他变量

注意:C中不允许将函数指针赋值到
void*