Linux何时/如何将共享库加载到地址空间? [英] When / How does Linux load shared libraries into address space?

查看:20
本文介绍了Linux何时/如何将共享库加载到地址空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题如下:

什么时候在程序中指定共享对象的地址?在链接期间?正在加载?如果我想在我的程序内部的 libc 中找到 system 命令的内存地址,我可以在 gdb 中轻松找到它,但是什么如果我不想将程序带入调试器?

When is the address of shared objects specified in programs? During linking? Loading? If I wanted to find the memory address of the system command inside of libc inside of my program I could find it easily in gdb, but what if I don't want to bring the program into a debugger?

这个地址可以从一个运行到另一个运行吗?是否有任何其他静态分析工具可以查看运行时库或函数将加载到该程序的内存空间中的位置?

Could this address change from run to run? Are there any other static analysis tool that will allow be to view where libraries or functions will be loaded into this program's memory space when run?

我希望在程序之外获得这些信息(即使用 objdump 等实用程序来收集信息)

I want this information outside of the program (ie. using utilities like objdump to gather information)

推荐答案

库由 ld.so(动态链接器或运行时链接器又名 rtld、ld-linux.so.2ld-linux.so.* 在 Linux 的情况下;glibc 的一部分).它被声明为所有动态链接 ELF 二进制文件的解释器"(INTERP;.interp 部分).所以,当你启动程序时,Linux 会启动一个 ld.so(加载到内存并跳转到它的入口点),然后 ld.so 会将你的程序加载到内存中,准备它然后运行它.您也可以使用

Libraries are loaded by ld.so (dynamic linker or run-time linker aka rtld, ld-linux.so.2 or ld-linux.so.* in case of Linux; part of glibc). It is declared as "interpreter" (INTERP; .interp section) of all dynamic linked ELF binaries. So, when you start program, Linux will start an ld.so (load into memory and jump to its entry point), then ld.so will load your program into memory, prepare it and then run it. You can also start dynamic program with

 /lib/ld-linux.so.2 ./your_program your_prog_params

ld.so 对所有需要的 ELF 文件进行实际的 openmmap,包括程序的 ELF 文件和所有 ELF 文件需要的库.此外,它填充 GOT 和 PLT 表并进行重定位解析(它将函数的地址从库写入调用站点,在许多情况下使用间接调用).

ld.so does an actual open and mmap of all needed ELF files, both ELF file of your program and ELF files of all neeeded libraries. Also, it fills GOT and PLT tables and does relocations resolving (it writes addresses of functions from libraries to call sites, in many cases with indirect calls).

您可以使用 ldd 实用程序获得的某些库的典型加载地址.它实际上是一个 bash 脚本,它设置了一个 ld.so 的调试环境变量(实际上是 LD_TRACE_LOADED_OBJECTS=1 在 glibc 的 rtld 的情况下)并启动一个程序.你甚至可以自己做而不需要脚本,例如使用 bash 轻松更改单次运行的环境变量:

The typical load address of some library you can get with ldd utility. It is actually a bash script, which sets a debug environment variable of ld.so (actually LD_TRACE_LOADED_OBJECTS=1 in case of glibc's rtld) and starts a program. You even can also do it yourself without needs of the script, e.g. with using bash easy changing of environment variables for single run:

 LD_TRACE_LOADED_OBJECTS=1 /bin/echo

ld.so 将看到这个变量,并将解析所有需要的库并打印它们的加载地址.但是使用这个变量集,ld.so 将不会真正启动程序(不确定程序或库的静态构造函数).如果 ASLR 功能 被禁用,加载地址将大部分时间相同.现代 Linux 通常启用了 ASLR,因此要禁用它,请使用 回声 0 |sudo tee/proc/sys/kernel/randomize_va_space.

The ld.so will see this variable and will resolve all needed libraries and print load addresses of them. But with this variable set, ld.so will not actually start a program (not sure about static constructors of program or libraries). If the ASLR feature is disabled, load address will be the same most times. Modern Linuxes often has ASLR enabled, so to disable it, use echo 0 | sudo tee /proc/sys/kernel/randomize_va_space.

您可以使用 binutils 中的 nm 实用程序在 libc.so 中找到 system 函数的偏移量.我认为,您应该使用 nm -D/lib/libc.soobjdump -T/lib/libc.so 和 grep 输出.

You can find offset of system function inside the libc.so with nm utility from binutils. I think, you should use nm -D /lib/libc.so or objdump -T /lib/libc.so and grep output.

这篇关于Linux何时/如何将共享库加载到地址空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆