我已经c++filt命令解码一个符号,相反的工具是什么,并修改一个符号名称?
如果我想调用dlsym()一个受损的C++函数名,这将非常有用.我宁愿不对代码中的名称进行硬编码,因为由于新的编译器版本或新编译器品牌的使用或目前由于编译多个平台而导致其随着时间的推移而发生变化.
是否有一种编程方式来获取在运行时表示C++函数的字符串,以便代码独立于编译器?可能这样做的一种方法是在编译时调用实用程序,为正在使用的编译器执行名称修改,并将适当的受损的C++符号名称插入到字符串中dlsym()以供使用.
这是我在这个站点上找到的最接近解决方案的方法,它通过使用固定的C样式名称来间接到您希望在库中定义的C++符号来实现dlsym(),但是如果您无法控制该库的内容提供,这不是一个选择.
我试图使用dlopen()和dlsym()在我的代码,并编译它gcc.
这是第一个文件.
/* main.c */
#include <dlfcn.h>
int main()
{
void *handle = dlopen("./foo.so", RTLD_NOW);
if (handle) {
void (*func)() = dlsym(handle, "func");
func();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是第二个文件.
/* foo.c */
#include <stdio.h>
void func()
{
printf("hello, world\n");
}
Run Code Online (Sandbox Code Playgroud)
这是我编译和运行代码的方法.
$ gcc -std=c99 -pedantic -Wall -Wextra -shared -fPIC -o foo.so foo.c
$ gcc -std=c99 -pedantic -Wall -Wextra -ldl -o main main.c
main.c: In function ‘main’:
main.c:10:26: warning: ISO C forbids initialization between function …Run Code Online (Sandbox Code Playgroud) 我有一个应用程序,其中一部分使用共享库.这些库在编译时链接.
在运行时,加载器期望共享对象在LD_LIBRARY_PATH,如果没有找到整个应用程序崩溃,错误"无法加载共享库".注意,不能保证客户端将拥有库,在这种情况下我想要应用程序留下合适的错误消息,独立部分也应该正常工作.
为此,我使用dlsym()并dlopen()在共享库中使用API.这个问题是如果我在API中有很多功能,我必须单独使用dlsym()和ptrs 访问它们,在我的情况下会导致内存损坏和代码崩溃.
这有什么替代方案吗?
让我为这个长期问题道歉.它尽可能短,但不幸的是,它不是很短.
我定义了两个接口,A和B:
class A // An interface
{
public:
virtual ~A() {}
virtual void whatever_A()=0;
};
class B // Another interface
{
public:
virtual ~B() {}
virtual void whatever_B()=0;
};
Run Code Online (Sandbox Code Playgroud)
然后,我有一个共享库"testc"构建类C的对象,同时实现A和B,然后传递指向它们的A接口的指针:
class C: public A, public B
{
public:
C();
~C();
virtual void whatever_A();
virtual void whatever_B();
};
A* create()
{
return new C();
}
Run Code Online (Sandbox Code Playgroud)
最后,我有一个第二个共享库"testd",它接受一个A*输入,并尝试将其转换为a B*,使用dynamic_cast
void process(A* a)
{
B* b = dynamic_cast<B*>(a);
if(b)
b->whatever_B();
else
printf("Failed!\n");
}
Run Code Online (Sandbox Code Playgroud)
最后,我有主要的应用程序,A*在库之间传递:
A* …Run Code Online (Sandbox Code Playgroud) 该POSIX标准增加了很多的库函数和其它标识符C语言.在dlsym()功能的描述中,它说(我强调):
概要
Run Code Online (Sandbox Code Playgroud)#include <dlfcn.h> void *dlsym(void *restrict handle, const char *restrict name);描述
在对dlsym()函数将获得符号的地址(一个功能标识符或数据对象标识符)...
C标准不保证函数指针可以转换为a void *,甚至不能保证指针的大小相同.这有效地增加了对C类型系统的额外限制.
我的问题是:
sizeof (function pointer) > sizeof (void *)dlsym()功能当我尝试运行脚本时,我收到以下错误:我只有执行权限:
uname: symbol lookup error: /home/dumindara/random/sotest/a.out: undefined symbol: dlsym
这是在我将LD_PRELOAD环境变量设置为之后/home/dumindara/random/sotest/a.out.
a.out有一个测试malloc功能,并在dlsym内部调用.
跑步时我没有遇到这个问题ls.大多数进程都会出现此错误.为什么会发生这种情况,我该怎么做才能使它发挥作用?
在我的C++程序中,如何在运行时以编程方式检测符号是否已通过Linux上的"strip"gnu开发工具剥离?
我想要一个函数定义,如果被剥离则返回true,否则返回false.
在"main()"上使用dlsym()可以有效地检测到它吗?
我目前工作的一个项目,我需要跟踪的几个系统调用和低级别的功能,如使用mmap,brk,sbrk.到目前为止,我一直在使用函数插入来执行此操作:我编写了一个与我正在替换的函数同名的包装函数(mmap例如),并通过设置LD_PRELOAD环境变量将其加载到程序中.我通过我加载的指针调用实际函数dlsym.
不幸的是,我想要包装的函数之一在sbrk内部使用dlsym,因此当我尝试加载符号时程序崩溃.sbrk在Linux中不是系统调用,所以我不能简单地使用syscall它来间接调用它.
所以我的问题是,如何在不使用相同名称的包装函数的情况下调用库函数dlsym?是否有任何编译器技巧(使用gcc)让我参考原始函数?
我正在使用dlsym在我的程序中查找符号,但它总是返回NULL,这是我没想到的.根据联机帮助页,如果某种方式存在错误,或者符号确实为NULL,则dlsym可能返回NULL.在我的情况下,我收到一个错误.我会告诉你我今晚做的MCVE.
这是instr.c的内容:
#include <stdio.h>
void * testing(int i) {
printf("You called testing(%d)\n", i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
一个非常简单的东西,只包含一个不起眼的示例函数.
这是test.c的内容:
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
typedef void * (*dltest)(int);
int main(int argc, char ** argv) {
/* Declare and set a pointer to a function in the executable */
void * handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
dlerror();
dltest fn = dlsym(handle, "testing");
if(fn == NULL) {
printf("%s\n", dlerror());
dlclose(handle);
return 1;
}
dlclose(handle);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我使用调试器逐步执行代码时,我看到dlopen正在返回一个句柄.根据联机帮助页,If filename is …
我想拦截应用程序对 dlsym 的调用。我尝试在 .so 中声明,以便我预加载 dlsym ,并使用 dlsym 本身来获取它的真实地址,但是由于很明显的原因,这不起作用。
有没有比获取进程的内存映射并使用 libelf 在加载的 libdl.so 中找到 dlsym 的真实位置更容易的方法?