Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dlsym -- get overridden symbol

I have an application dynamically loading libraries which dynamically load libraries which...

In Windows, I'm able to iterate over all loaded modules looking for the symbol I'm interested in. Don't know how to do that in Unix/Linux environment. I know I may use dlsym(dlopen(0, flag)) or dlsym(RTLD_DEFAULT / RTLD_NEXT) for first two symbols and know the order of the modules to search in -- just how may I get deeper and get all definitions of given symbol?

like image 249
ciesizdz Avatar asked Feb 22 '23 06:02

ciesizdz


2 Answers

To find a symbol in a shard object, open it with dlopen.

 void* foobar = dlopen ("/usr/local/lib/foobar.so", RTLD_NOW);
 void* mysymbol = dlsym (foobar, "mysymbol");

Update Here's a program that iterates over all symbols named "foo". This is not POSIX but GNU libs. I am almost sure POSIX does not provide such capabilities.

#define _GNU_SOURCE 
#include <link.h>
#include <dlfcn.h>
#include <stdio.h>

void doit (const char* s)
{
    void* obj = dlopen (s, RTLD_LAZY);
    void* fcn = dlsym (obj, "foo");
    if (fcn)
        printf ("Object %s has 'foo' at addr %p\n", *s ? s : "(exe)", fcn);
}    
int cb (struct dl_phdr_info *info, size_t size, void *data)
{
    doit (info->dlpi_name);
    return 0;
}    
int main ()
{
    dl_iterate_phdr (cb, 0);    
    return 0;
}

Here's the output:

Object (exe) has 'foo' at addr 0xb76f8418
Object (exe) has 'foo' at addr 0xb76f8418
Object /tmp/libfoo.so has 'foo' at addr 0xb76f8418
Object /tmp/libfoo1.so has 'foo' at addr 0xb76f5418
Object /tmp/libfoo2.so has 'foo' at addr 0xb76f2418

There are some duplicates but this is a minor problem.

like image 54
n. 1.8e9-where's-my-share m. Avatar answered Mar 03 '23 09:03

n. 1.8e9-where's-my-share m.


Answering own question to make the life of people searching for the solution easier. There's no unified way, one wanting to iterate on loaded modules should search for the following commands/data types (the experts are invite to comment on that):

Windows:
MODULEENTRY32, CreateToolhelp32Snapshot, Module32First, Module32Next

Linux:
as described in n.m.'s answer, return non-zero from the callback when proper module found (ends the loop).

AIX:
loadquery(L_GETINFO, buffer, size), struct ld_info.

HP-UX:
dlget, dlgetname (if you need the module path).

Solaris:
ldinfo, Link_map.

Additionally, I'd recommend to dlopen the modules and get the symbol from a new handle to have library's reference count incremented which prevents it from being unloaded. At least on AIX it may have a side effect of the library loaded and initialized once again, but it's in most cases better than attempting to call a function from the unloaded library.

like image 39
ciesizdz Avatar answered Mar 03 '23 09:03

ciesizdz