1

I want to list all libraries (.so) loaded into app address space. I use the procfs and read info from /proc/self/maps. I there existing way to detect file is executable or .so? Or I need to compare each found module name with value of /proc/self/exe?

UPD Some more questions.

When I parse /proc/self/maps procfs file, I wan to find the base addr for each found loaded .so module, but I can find the way to make it without dl* functions call.

I try to use dladdr:

    Dl_info info;
    int dladdrRes = dladdr((void*)(mmIt->startAddr), &info);
    if (!dladdrRes) continue;

    std::string modName = info.dli_fname;
    void *modBase       = info.dli_fbase;

but modBase is not an addr which the 'dlopen' function returns. Only the way, which calls the 'dlopen' function works:

dlopen( filename.c_str(), RTLD_NOW|RTLD_NOLOAD|RTLD_LOCAL );

My idea is that: when I parse /proc/self/maps, I know names of all loaded modules, and I don' need to call kernel to find the base of loaded module. As I find, it is my wrong.

Bernd Jacobi
  • 571
  • 2
  • 5
  • 18
  • Your second idea seems like the most reasonable shortcut, avoiding difficulties like opening all those files and parsing their ELF headers. – Kaz Jul 09 '14 at 23:03
  • Parsing ELFs by myself seems as not a good idea, I want to use only public documented APIs – Bernd Jacobi Jul 10 '14 at 03:07

1 Answers1

1

The output of /proc/self/maps is

address           perms offset  dev   inode       pathname

Executables have the x permission bit set. By default there are a few maps that are executable but have no file on disk (like e.g. vdso). So all you have to do is extracting those entries of maps that have the x permission bit set and have a matching file on disk.

Note that it's not really necessary for an executable map to be in a particular file format. For example wine maps Windows executables (which are PE files; any may not even have executable bit set on the file system) with the exectuable permission bit, so that the code in them can be executed. So it's generally a good idea to just look at the /proc/self/maps and not try to infer anything from the files on storage.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Currently i parse /proc/self/maps, read the flags, and skip all lines without x (executabe) flag. Also, I skip [vdso], [stack], [heap] and same entries. Next, I try to examine each module for my own conditions, and I fails on the main executable - dlopen reports that it can operate/load the executable (I think it means it can load only .so files) – Bernd Jacobi Jul 10 '14 at 03:03
  • @BerndJacobi: dlopen has certain expectations about the file format of the executable. Specifically I expects to see a *shared object*, i.e. a library that has defined a soname and exports a symbol table. *Your question strongly hints, that you're coming from the Windows world and expect that you can subject executables to the same rules as libraries, like you can do with GetModuleHandle. dlopen is not a substitute for GetModuleHandle, it works very different.* In Windows GetModuleHandle is effectively a syscall into the kernel. dlopen however does all its magic without kernel support. – datenwolf Jul 10 '14 at 09:00
  • @BerndJacobi: Note that it's perfectly possible that shared objects can also be executables (or executables can be shared object). Try this on your shell `~/> /lib/libc.so` (you'll have to add the version after the .so, for example `libc.so.6`). What dlopen expects is a binary in either ELF or a.out format (usually just ELF format is supported on most common installations), that declares itself to be a shared object and exports a certain minimum symbol table. – datenwolf Jul 10 '14 at 09:09