我试图使用libffi访问macos(10.11)上的stat()。这是SWI-Prolog基于FFI的新外部接口的一部分。此接口解析<sys/stat.h>
标头以获取函数原型和struct stat
类型。但是,我得到了虚假的价值观。如果我编译下面的代码并从生成的mystat
链接.dylib
。
#include <sys/stat.h>
int
mystat(const char *name, struct stat *buf)
{ return stat(name, buf);
}
我怀疑我从stat
得到错误的dlsym()
函数。在/usr/lib/libc.dylib
和/usr/lib/libSystem.B.dylib
上进行了尝试。这给出了相同的结果。如果我从上面的dylib上运行nm
我得到了
U _stat$INODE64
。 dlsym
stat$INODE64
无效534_> nm /usr/lib/libc.dylib | grep stat
0000000000001ac5 T R8289209$_pthread_attr_setdetachstate
0000000000001af7 T R8289209$_stat
U _pthread_attr_setdetachstate
U _stat
。看看libc.dylib,我们得到了
{{1}}
两者如何相关?任何人都有任何线索可能会发生什么?
答案 0 :(得分:0)
您要查找的符号在/usr/lib/system/libsystem_kernel.dylib
中定义:
$ ~ nm -g /usr/lib/system/libsystem_kernel.dylib | grep '_stat\$INODE64'
0000000000002ed0 T _stat$INODE64
可以使用dlsym
找到它
#include <sys/stat.h>
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
int
(*real_stat)(const char *path, struct stat *buf);
int main() {
const char *path = "/usr/lib/system/libsystem_kernel.dylib";
int err;
struct stat st;
void *lib = dlopen(path, RTLD_LOCAL);
real_stat = dlsym(lib, "stat$INODE64");
if((err = real_stat(path, &st)))
fprintf(stderr, "Can't stat %s: %s\n", path, strerror(err));
printf("%s inode: %lld\n", path, st.st_ino);
dlclose(lib);
return 0;
}
real_stat
返回的索引节点编号与stat(1)
返回的索引节点编号匹配:
$ ~ cc stat.c
$ ~ ./a.out
/usr/lib/system/libsystem_kernel.dylib inode: 4335860614
$ ~ stat -r /usr/lib/system/libsystem_kernel.dylib
16777220 4335860614 0100755 1 0 0 0 545424 1564436981 1564436981 1565194657 1564436981 4096 448 524320 /usr/lib/system/libsystem_kernel.dylib
在某些情况下,stat
可能会被这样错误地声明:
struct stat;
int stat(const char *restrict path, struct stat *restrict buf);
int mystat(const char *path, struct stat *buf) {
return stat(path, buf);
}
该库确实引用了旧版stat
:
$ ~ cc -dynamiclib wrong-stat.c -o libwrongstat.dylib
$ ~ nm libwrongstat.dylib
0000000000000f70 T _mystat
U _stat
U dyld_stub_binder
<sys/stat.h>
使用带有后缀stat
的特殊assembler names for functions声明$INODE64
,以避免与现有stat
发生冲突(有关详细信息,请参见stat(2)
)。如果声明stat
以后缀引用新的汇编程序名称,则该库可以固定:
struct stat;
int stat(const char *path, struct stat *buf) __asm("_stat$INODE64");
int mystat(const char *path, struct stat *buf) {
return stat(path, buf);
}
$ ~ cc -dynamiclib correct-stat.c -o libcorrectstat.dylib
$ ~ nm libcorrectstat.dylib
0000000000000f70 T _mystat
U _stat$INODE64
U dyld_stub_binder
但老实说,我会使用<sys/stat.h>
来提取正确的符号声明。