0

I wrote next program:

#include <iostream>
#include <dlfcn.h>

int main(int argc, char** argv)
{
    typedef void* (*fptr)();
    fptr func;
    void *handle = dlopen(0, RTLD_NOW);
    std::cout << dlerror() << std::endl;    
    *(void **)(&func) = dlsym(handle, "__libc_start_main");
    std::cout << dlerror() << std::endl;

    std::cout << handle << " " << func << "\n";

    dlclose(handle);
return 0;
}

and try to compile in next way:

g++ -rdynamic main.cpp -ldl -o test

When I run this program I don’t see any message. Why?

Thank U for attention.

tpatja
  • 690
  • 4
  • 11
user1358552
  • 83
  • 1
  • 4

2 Answers2

5

Your process is faulting because dlerror() is only valid to call in an error condition, which you never validated actually happened prior to invocation.

From the Linux docs:

The function dlerror() returns a human readable string describing the most recent error that occurred from dlopen(), dlsym() or dlclose() since the last call to dlerror(). It returns NULL if no errors have occurred since initialization or since it was last called.

In other words, your dlopen succeeded, so NULL is returned from dlerror(). That NULL is then sent as a char * to std::cout, and kerboom.

Bottom line: check your error conditions before invoking dlerror(). Try this instead:

#include <iostream>
#include <dlfcn.h>

int main(int argc, char** argv)
{
    typedef void* (*fptr)();
    fptr func;

    void *handle = dlopen(0, RTLD_NOW);
    if (handle == nullptr)
    {
        std::cout << dlerror() << std::endl;
        exit(EXIT_FAILURE);
    }

    func = (fptr)dlsym(handle, "__libc_start_main");
    if (!func)
    {
        std::cout << dlerror() << std::endl;
        exit(EXIT_FAILURE);
    }

    std::cout << handle << " " << func << "\n";

    dlclose(handle);
    return 0;
}
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
2

This is (likely) undefined behavior:

std::cout << dlerror() << std::endl; 

...unless dlerror is actually non-null (which it probably isn't). It should be:

char* error = dlerror();
if (error != 0)
    std::cout << error << std::endl;

...or:

void *handle = dlopen(0, RTLD_NOW); 
if (handle == 0)
    std::cout << dlerror() << std::endl;

Also, you probably should abort if dlerror is non-null (or handle is null), because calling dlsym on an null handle is also undefined behavior.

See Why does std::cout output disappear completely after NULL is sent to it.

Community
  • 1
  • 1
netcoder
  • 66,435
  • 19
  • 125
  • 142
  • Thank U. This is last problem how to do with member function. typedef void (A::*fptr)(); and than try something like func = (fptr)dlsym(handle, "test"); Than this is compile error because he dont know how to cast void to fptr. Can U help me with this? – user1358552 May 14 '14 at 16:56