我正在尝试使用libffi访问macos (10.11)上的stat()。这是SWI-Prolog新的基于FFI的外部接口的一部分。此接口解析<sys/stat.h>标头以获得函数原型和struct stat类型。然而,我得到的是虚假的值。如果我编译下面的代码并从生成的.dylib链接mystat,它就能正常工作。
#include <sys/stat.h>
int
mystat(const char *name, struct stat *buf)
{ return stat(name, buf);
}我怀疑我从dlsym()得到了一个错误的stat函数。已在/usr/lib/libc.dylib和/usr/lib/libSystem.B.dylib上试用。这给出了相同的结果。如果我在上面的dylib上运行nm,我会得到U _stat$INODE64。dlsym不能在stat$INODE64上工作。看看我们得到的libc.dylib
534_> nm /usr/lib/libc.dylib | grep stat
0000000000001ac5 T R8289209$_pthread_attr_setdetachstate
0000000000001af7 T R8289209$_stat
U _pthread_attr_setdetachstate
U _stat这两者之间有什么关系?有谁知道这是怎么回事吗?
发布于 2019-08-19 19:05:04
您要查找的符号已在/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返回的inode编号与stat(1)返回的inode编号相匹配
$ ~ 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>使用带有$INODE64后缀的特殊assembler names for functions声明stat,以避免与现有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>来提取正确的符号声明。
https://stackoverflow.com/questions/48380955
复制相似问题