问题
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