通过运行应用程序以编程方式确定正在使用的共享库
是否可以(如果可以,如何)确定应用程序在运行时使用的共享库?基本上,我可以通过编程方式获取 ldd 的输出吗?首选的 C/C++ 解决方案不仅仅跳转到在命令行上执行 ldd。
考虑以下几点: 我有一个驱动程序应用程序,它从共享库 libfoo
调用 doAction()
。我编译应用程序一次,然后将 LD_LIBRARY_PATH 设置为包含定义了 doAction() 符号的 libfoo 的适当目录。这样,我可以在不同的 libfoo 中实现多个 doAction() ,但只编译一次应用程序。
一个现实世界的例子是一位教授让一班学生实现doAction()
。学生无需针对每个学生的 doAction()
实现编译测试工具,而是提交一个共享库,教授只需更改 LD_LIBRARY_PATH
即可评估每个学生。
我获取当前正在使用的库的目标是在运行时对库执行 md5sum
以确保我调用正确的库。在人为的示例中,所有学生都将提交其库的 md5sum
,教授可以将正在运行的可执行文件 + 共享库(数据库查找、日志到文件等)匹配给学生,以防止设置 LD_LIBRARY_PATH
时发生意外,影响了其他学生的成绩(忘记将 LD_LIBRARY_PATH
更改为 David 的目录,然后再次运行 Bill 的目录) libfoo
)。
Is it possible to (and, if so, how does one) determine the shared libraries of an application that are used by an application at runtime? Basically, can I programmatically obtain the the output of ldd
? Preferred C/C++ solution does not just jump to execute ldd on the command-line.
Consider the following:
I have a driver application that calls doAction()
from a shared library libfoo
. I compile the application once and then set LD_LIBRARY_PATH
to an appropriate directory containing a libfoo
with the doAction()
symbol defined. This way, I can have multiple implementations of doAction()
in different libfoo
s but only ever compile an application once.
A real world example would be a professor having a class of students implement doAction()
. Instead of compiling a test harness against each student's implementation of doAction()
, the students submit a shared library and the professor can simply change LD_LIBRARY_PATH
to evaluate each student.
My goal in obtaining the library currently being used is to perform an md5sum
on the library at runtime to ensure I'm calling the correct library. In the contrived example, all students would submit the md5sum
of their library and the professor could match the running executable + shared library (database lookup, log to file, ...) to the student, to prevent an accident in setting LD_LIBRARY_PATH
effecting another student's grade (forgot to change LD_LIBRARY_PATH
to David's directory and ran again with Bill's libfoo
).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果您使用的是 Linux,则可以使用 dl_iterate_phdr 函数:
http://linux.die.net/man/3/dl_iterate_phdr
If you're using Linux, you can use the
dl_iterate_phdr
function:http://linux.die.net/man/3/dl_iterate_phdr
由于看起来您正在使用 UNIX-y 的东西,因此只需使用 dlopen 即可,而不是针对丢失的符号动态链接您的驱动程序应用程序。
完整的顺序是:
像这样:
注意:
void (*)()
),您可以通过目录名称和符号名称进行配置,并且它可以工作 对于多个测试extern "C" void doAction()
以避免这种情况。RTLD_LOCAL
标志应该阻止一个学生图书馆中的任何内容干扰另一个学生的图书馆(如果您不卸载),但添加其他标志可能是明智的RTLD_NOW
将导致dlopen
失败(因此您可以通过失败来优雅地处理它)他们):否则当您调用doAction
时,您的程序可能会崩溃。尽管我认为上述内容比您直接寻求帮助的解决方案更好,但我在仔细检查文档时也找到了对
dl_iterate_phdr
的引用。如果您使用的是 Linux,并且dl_phdr_info.dlpi_name
实际上是文件名……您也许可以通过这种方式获取它。但我仍然认为它丑陋得多。
Since it looks like you're using something UNIX-y, just use
dlopen
instead of dynamically linking your driver app against the missing symbol.Full sequence is:
like so:
Notes:
void (*)()
), you could make this configurable by directory name and symbol name, and it'd work for more than one testextern "C" void doAction()
to avoid that.RTLD_LOCAL
flag should stop anything in one student's library interfering with another (if you don't unload), but there are other flags it may be sensible to addRTLD_NOW
will causedlopen
to fail if the student lib has an unresolved external reference it can't figure out (so you can handle it gracefully, by failing them): otherwise your program may just crash when you calldoAction
.Although I think the above is better than the solution you're directly asking for help with, I did also find a reference to
dl_iterate_phdr
while double-checking the docs. If you're on Linux specifically, and if thedl_phdr_info.dlpi_name
is actually the filename ... you might be able to get it that way.I still think it's much uglier, though.
在运行时,它不是一个应用程序,而是一个进程。
如果进程的pid为1234,则可以通过读取
/proc/1234/maps
(或更详细的/proc/1234/smaps
)来获取其内存映射。该映射特别列出了 mmap 编辑的文件(尤其是共享库)。从应用程序内部,阅读/proc/self/maps
尝试
理解我的意思。
顺便说一句,如果您有地址,dladdr 函数会提供有关最近的地址的信息符号和共享对象...
附录
正如 Rob Mayoff 回答,dl_iterate_phdr 可能是 Linux 上最好的解决方案
At runtime, it is not an application, it is a process.
If the process has pid 1234, you can get its memory map by reading
/proc/1234/maps
(or/proc/1234/smaps
which is more detailed). That map lists in particular mmap-ed files (notably shared libraries). From inside the application, read/proc/self/maps
Try
to have an idea of what I mean.
By the way, if you have an address, the dladdr function gives information about the nearest symbol and shared object...
addenda
And as Rob Mayoff answered, dl_iterate_phdr is probably the best solution on Linux
如果这是 Linux(我怀疑是否有通用的 POSIX 方法可以做到这一点,但我可能是错的),您可能对 /proc/(pid)/maps 的内容感兴趣。这给出了进程的映射内存范围,您可以搜索 md5sum() 函数的地址属于哪个范围。
If this is Linux (I doubt there's a generic POSIX way to do this but I could be wrong), you may be interested in the contents of /proc/(pid)/maps. This gives the mapped memory ranges for your process and you could search for which of the ranges your md5sum() function's address falls in.
如果您使用的是 linux/unix,则可以使用 strace ,例如
strace -o strace .log -f Students_binary
。 Strace 跟踪所有系统调用,包括打开库的调用。然后,您可以解析 strace.log 来查找任何文件的所有打开情况,并对所有打开的文件执行 md5sum 。If you're in linux/unix, you could use strace like
strace -o strace.log -f students_binary
. Strace traces all system calls, including the calls to open a library. Then you could parsestrace.log
for all openings of any file and perform themd5sum
on all open files.