我正在尝试使用dlopen和dlsym动态加载统计信息功能。
stat familly中的函数包装在相应的函数__xstat
,__xstat64
itp中。
下面的代码片段是在32位模式下编译时可以编译和工作的(为示例起见,包含了sys/stat.h
以获取统计信息结构)
#include <iostream>
#include <dlfcn.h>
#include <sys/stat.h>
typedef int (*xstat_f) (int __ver, const char *__filename, struct stat *__stat_buf);
int main()
{
auto* h = dlopen("libc.so.6", RTLD_LAZY);
if(!h)
{
return 1; // invalid handle
}
auto f = (xstat_f)dlsym(h, "__xstat");
if(!f)
{
return 1; // invalid handle
}
struct stat s = {};
const auto r = f(3, "/tmp", &s);
if (r != 0)
{
perror("stat");
return errno;
}
return 0;
}
g++ main.cpp -o main -ldl -m32
在没有-m32
开关的情况下在64位计算机上编译的可执行文件将返回EINVAL(无效参数)。
原因是什么?
我也做了一个最低限度的测试
#include <iostream>
#include <sys/stat.h>
int main(){
struct stat s;
const auto x = stat("/tmp", &s);
if(x != 0) return errno;
return 0;
}
并在32位和64位可执行文件上都使用objdump -T
,表明stat
被解析为__xstat
,因此我使用的是正确的符号。我也尝试过将__xstat/__xstat64
,struct stat/stat64
组合使用,结果相同。
答案 0 :(得分:0)
__ xstat声明如下:
int __xstat(int ver, const char *path, (struct stat *stat_buf))
在文档参数ver中的描述类似于ver shall be 3 or the behavior of these functions is undefined
,这并不完全正确,因为在源代码中,_STAT_VER_LINUX
的定义如下:
#ifndef __x86_64__
# define _STAT_VER_LINUX 3
#else
# define _STAT_VER_LINUX 1
#endif
这就是为什么对__xstat
的64位调用失败了,参数ver
应该设置为1,而在32位编译时应该设置为3的原因。