Address range of a dynamically loaded library under Linux

蓝咒 提交于 2019-12-11 09:51:31

问题


I have a working program that loads plugins with dlopen.

New requirement: at some point in the code, I'm given a pointer, and I need to test whether this pointer points into the code or static data of a plugin.

bool is_pointer_into_plugin(void *p, void *handle);

Equivalently, I need to retrieve the plugin into which a pointer points, if any. I also need to know if the pointer points into the main program's code or static data (and ideally, distinguish between read-only and read-write areas).

void *handle plugin_containing_pointer(void *p);

Equivalently, I need to be able to retrieve the extent (address and size) at which a plugin is mapped. I also need this information for the main program.

How can I implement is_pointer_into_plugin, or plugin_containing_pointer, or something equivalent?

I can change the call to dlopen if necessary. The lookup should be reasonably fast as possible, the load-time code doesn't need to be fast. Running the plugins in separate processes and communicating through shared memory is not an option.

My program runs under Linux (and Windows, but that's another question). Future portability to other unix systems (at least to OSX) would be a plus.


回答1:


One way (completely specific to Linux) is to parse /proc/self/maps (see also Understanding Linux /proc/id/maps), which describes the process's memory mapping. Each dynamically loaded library has one or more entry (usually 3) that gives its address range, its access permissions and the file name. Here's an example showing the mapping of the C library:

f7622000-f7775000 r-xp 00000000 08:06 6950542                            /lib/tls/i686/cmov/libc-2.11.1.so
f7775000-f7777000 r--p 00153000 08:06 6950542                            /lib/tls/i686/cmov/libc-2.11.1.so
f7777000-f7778000 rw-p 00155000 08:06 6950542                            /lib/tls/i686/cmov/libc-2.11.1.so

The first column gives the address range, the second column gives the permissions, and the third gives the full path to the library (or to the main executable). Entries with an empty last column or a last column that isn't a file name correspond to non-file-backed areas (stack, heap, etc.). The permissions r-xp indicate the code, r--p is read-only data, rw-p is mutable data.

If the plugin file is renamed or deleted, this will be reflected in /proc/self/maps. To avoid problems if this happens, read the information as soon as possible after calling (dlopen); note that there is an unavoidable race condition. The plugin file can be tracked by device and inode instead: open the file, call dlopen on /dev/fd/NUM, read /proc/self/maps, compare the 4th and 5th columns with the values obtained with fstat.




回答2:


One way, if you control the plugin enough -- playing with linker scripts should do the trick --, would be to ensure having specified symbols at start and end -- i.e. similar to __executable_start, _etext, _edata, _end -- and then use dlsym to get their addresses. You can probably get the same effect on all systems with dynamic libraries, thus pushing most the system dependencies on the build side.



来源:https://stackoverflow.com/questions/12589443/address-range-of-a-dynamically-loaded-library-under-linux

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!