下面是我想使用libtool的libltdl dlpreopening的代码类型的简单示例:
https://github.com/EmmaJaneBonestell/dlopen-sample
我希望能够重写各种使用libdl函数( dlopen、dlsym等)的项目,而使用libtool的libltdl预打开/预加载机制。从libtool的文档中,它将在编译时链接对象,从而产生真正的静态可执行文件。它适用于不支持动态加载的系统。
如果您使用它编译和链接这些对象,libtool将运行它的一些脚本,并创建必要的数据结构,我相信会执行损坏和剥离,以允许重复的符号名。
即使在查看了libtool源代码中的示例、阅读了它的全部文档并查看了测试套件中的相关测试(例如,test 118和120)之后,我仍然无法做到这一点。
除了libtool本身之外,我在任何地方都没有提到这个功能。我确实看到它在Graphviz中以一种过于复杂的方式使用,但这方面的文档也很少。
我真的不是一个程序员,更多的是一个修补者。对于我来说,使用libltdl作为标准dlopen/dlsym的包装器是非常容易的。
我认为我的主要问题是弄清楚如何为预打开的对象返回一个适当的句柄,尽管我可能做错了其他事情。
文档指出,lt_dlopen可以处理预加载的静态模块,但它似乎不接受任何可能的引用,我可以想象。
我也不希望不得不调用libtool,而是使用c‘’est la vie。
我没有费心地包括我尝试过的任何代码明智的东西(在本例中),因为我尝试过如此混乱的东西,以至于我觉得展示它真的会让人感到困惑。
当前的libtool文档:https://www.gnu.org/software/libtool/manual/libtool.html
发布于 2021-06-06 21:58:05
显然,libtool要求.la文件存在并正确声明它的rpath,即使它不会用于这个真正静态的二进制文件中的任何东西。
Libtool的文档相当清楚地表明,您的“模块”文件应该包含以下预处理器宏,以便导出所有符号。
#define SYMBOL SOURCEFILENAME_LTX_SYMBOL在我的例子中,这会导致溴素c和氯化c分别具有以下特性。
#define chemical_name bromine_LTX_chemical_name
#define chemical_name chlorine_LTX_chemical_name在我的问题中仍然假设代码存储库,下面的命令是如何使用libtool自动dlpreopen您的二进制文件的示例。
libtool --mode=compile gcc -static -fPIC -fno-plt -c bromine.c
libtool --mode=compile gcc -static -fPIC -fno-plt -c chlorine.c
libtool --mode=link gcc -all-static -fPIC -fno-plt -o bromine.la -rpath $PWD -module -no-undefined -avoid-version bromine.lo
libtool --mode=link gcc -all-static -fPIC -fno-plt -o chlorine.la -rpath $PWD -module -no-undefined -avoid-version chlorine.lo但是,对我来说,跳过每一个libtool步骤并简单地声明main.c本身中所需的结构数组要简单得多。将重新定义的函数/符号声明为extern,而不管它们的类型如何,并创建一个名为lt_dlsymlist的lt__PROGRAM__LTX_preloaded_symbols数组。第一个元素是程序本身,最后一个元素是{0,(void *) 0}。在这两者之间,一个struct行将声明dlpreopened对象/静态存档的basename,文件后缀为".a“。
它将具有.a后缀,而不管它是.a、.o、.c还是任何其他文件的。下一个结构将是您想要使用的从它导出的所有符号,然后,如果您愿意,可以使用另一个文件名、它的符号等等。符号名将与所有其他字段一样使用(void *) &符号而不是(void *) 0。
extern int bromine_LTX_chemical_name();
extern int chlorine_LTX_chemical_name();
const lt_dlsymlist lt__PROGRAM__LTX_preloaded_symbols[] ={
{"@PROGRAM@", (void *) 0},
{"chlorine.a", (void *) 0},
{"chlorine_LTX_chemical_name", (void *) &chlorine_LTX_chemical_name},
{"bromine.a", (void *) 0},
{"bromine_LTX_chemical_name", (void *) &bromine_LTX_chemical_name},
{0, (void *) 0}
};最后,lt_dlopen并不反映lt_dlsymlist声明--理想情况下,您将只调用文件的basename,而不需要它的扩展名。例如:
handle = lt_dlopen("chlorine");而非
handle = lt_dlopen("chlorine.a")但是,我相信无论您提供的扩展是什么,它都会工作,因为lt_dlopen函数剥夺了扩展。
按照上述规定的方式进行编译可以将您的编译减少到一行,并且完全避免libtool。例如
gcc -static -Wl,-static -fPIC -fno-plt -Wl,-z,now,--no-undefined -o main main.c bromine.c chlorine.c -lltdl -ldl我还验证了这会产生一个真正的静态二进制文件,方法是将所有内容链接到libltdl的调试构建中--但是从其中删除预打开(没有libdl,等等)。
$./main HOBr HOCl
loaders: lt_preopen
try_dlopen (bromine, (null))
tryall_dlopen (bromine.a, lt_preopen)
Calling lt_preopen->module_open (bromine.a)
Result: Success
try_dlopen (chlorine, (null))
tryall_dlopen (chlorine.a, lt_preopen)
Calling lt_preopen->module_open (chlorine.a)
Result: Success
The IUPAC name of HOBr is hypobromous acid.
The IUPAC name of HOCl is hypochlorous acid.https://stackoverflow.com/questions/67855638
复制相似问题