1

Is it possible to retrieve programmatically and in a cross-platform way a list of the shared libraries (*.dll, *.so, *.dylib) linked to the current process?

For example:

vector<string> getLinkedSharedLibraries() {
  // ...
}

vector<string> sharedLibraryList = getLinkedSharedLibraries();
for (list<string>::iterator it = sharedLibraryList.begin(); it != sharedLibraryList.end(); ++it)
  cout << *it << endl;

which would return:

/usr/lib/libz.1.dylib
/usr/lib/libSystem.B.dylib
...

I was thinking about using OS commands such as ldd on Linux and otool -L on Mac, and then to eventually use [DY]LD_LIBRARY_PATH to retrieve there absolute path. But I don't find a similar way on Windows.

Alternatively, is there any existing library doing such kind of thing?

FabienRohrer
  • 1,794
  • 2
  • 15
  • 26
  • There is no language named "C/C++", and your code is C++. Please correct your title. – Tim Čas Feb 19 '15 at 15:00
  • The solutions on windows are quite disappointing: http://stackoverflow.com/questions/1993673/what-is-the-equivalent-of-linuxs-ldd-on-windows – FabienRohrer Feb 19 '15 at 15:39
  • Aside: why isn’t the function returning the libraries, and instead passes them as an out parameter? This is generally not recommended – i.e. there are very few valid use-cases for this. – Konrad Rudolph Feb 19 '15 at 17:42
  • You're right. I have done that to avoid a copy, but it seems modern compiler are dealing with this better (http://stackoverflow.com/questions/514908/best-way-to-return-list-of-objects-in-c). I'm editing the question.. – FabienRohrer Feb 20 '15 at 07:51

1 Answers1

3

This is just one of those things that Windows does better.. You don't need a tool and it gives more information about and it's easy to retrieve..

There isn't much use case in "knowing" whether a specific module was loaded or not. It's either you loaded it, or you didn't.

enter image description here

#include <windows.h>
#include <tlhelp32.h>
#include <vector>
#include <iostream>
#include <sstream>

bool GetModules(std::vector<MODULEENTRY32> &modules)
{
    void* hSnap = nullptr;
    MODULEENTRY32 Mod32 = {0};

    if ((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId())) == INVALID_HANDLE_VALUE)
        return false;

    Mod32.dwSize = sizeof(MODULEENTRY32);
    while (Module32Next(hSnap, &Mod32))
    {
        modules.push_back(Mod32);
    }

    CloseHandle(hSnap);
    return true;
}


std::string ModuleToString(MODULEENTRY32 Mod32)
{
    auto to_hex_string = [](std::size_t val, std::ios_base &(*f)(std::ios_base&)) -> std::string
    {
        std::stringstream oss;
        oss << std::hex << std::uppercase << val;
        return oss.str();
    };

    std::string str;
    str.append("  =======================================================\r\n");
    str.append("  Module Name:             ").append(Mod32.szModule).append("\r\n");
    str.append("  =======================================================\r\n\r\n");
    str.append("  Module Path:             ").append(Mod32.szExePath).append("\r\n");
    str.append("  Load Count (Global):     ").append(std::to_string(static_cast<int>(Mod32.GlblcntUsage != 0xFFFF ? Mod32.GlblcntUsage + 1 : 0)).c_str()).append("\r\n");
    str.append("  Load Count (Process):    ").append(std::to_string(static_cast<int>(Mod32.ProccntUsage != 0xFFFF ? Mod32.ProccntUsage + 1 : 0)).c_str()).append("\r\n");
    str.append("  Base Address:            0x").append(to_hex_string(reinterpret_cast<std::size_t>(Mod32.modBaseAddr), std::hex).c_str()).append("\r\n");
    str.append("  Base Size:               0x").append(to_hex_string(Mod32.modBaseSize, std::hex).c_str()).append("\r\n\r\n");
    str.append("  =======================================================\r\n");
    return str;
}


int main()
{
    std::vector<MODULEENTRY32> modules;

    if (GetModules(modules))
    {
        for (auto &&it : modules)
        {
            std::cout<<ModuleToString(it)<<"\n";
        }
    }
    return 0;
}
Brandon
  • 22,723
  • 11
  • 93
  • 186