How can dlerror() return NULL if dlopen() fails?

11,809

Solution 1

In this code:

handle=dlopen(mod->binary_file, RTLD_NOW); 

if (!handle) {
    LOG( " could not open file [%s]: %s\n",
         mod_cfg->binary_file, dlerror() );

the most likely way I can think of for the dlerror() to return NULL here is if LOG itself calls one of the dl* routines (which would clear the error state that dlerror returns).

So,

  • show us what LOG macro (if indeed it is a macro) expands to, and
  • run the program under GDB, set breakpoints on dlopen, dlmopen, dlsym and dlvsym, and observe that one of them is called after your call to dlopen above and before your call to dlerror.

Solution 2

I would use a debugger like gdb.

If you cannot use it, try to use strace or ltrace on the process doing the dlopen

Also, clear errno before calling dlopen and display it (or print it under the debugger) just after the failing dlopen.

Check with file, objdump, and nm -D that your dlopen-ed *.so file has all the required properties (e.g. symbols).

Perhaps the memory address space of the process doing the dlopen is so full (or has reached some resource limits) that some internal malloc inside libdl.so fails (e.g. the one used by dlerror).

Share:
11,809
Mike Albren
Author by

Mike Albren

Updated on June 05, 2022

Comments

  • Mike Albren
    Mike Albren almost 2 years

    I am working on system that loads all *.so modules library automatically by call a script.

    I tried to update one of the modules to support XML-RPC. I used the library ibxmlrpc-c3-dev on Ubuntu 10.10. The problem that dlopen() fails after my changes and dlerror() returns NULL. The compilation does not return any error.

    How can I debug and fix this issue? Below is the code:

    #include "stdlib.h"
    #include "stdio.h"
    #ifndef WIN32
    #include "unistd.h"
    #endif
    
    #include "xmlrpc-c/base.h"
    #include "xmlrpc-c/server.h"
    #include "xmlrpc-c/server_abyss.h"
    
    #include "config.h"  /* information about this build environment */
    

    And, I added this function , most of the lines are commented out ,even though dlopen() fails:

    int RPC_Server(int           const port) {
    
       // xmlrpc_server_abyss_parms serverparm;
        //xmlrpc_registry * registryP;
        xmlrpc_env env;
    
    
    
        xmlrpc_env_init(&env);
    
        //registryP = xmlrpc_registry_new(&env);
    
       // xmlrpc_registry_add_method(
        //    &env, registryP, NULL, "sample.add", &sample_add, NULL);
    
        /* In the modern form of the Abyss API, we supply parameters in memory
           like a normal API.  We select the modern form by setting
           config_file_name to NULL:
        */
      //  serverparm.config_file_name = NULint
        RPC_Server(int           const port) {
    
           // xmlrpc_server_abyss_parms serverparm;
            //xmlrpc_registry * registryP;
            xmlrpc_env env;
    
    
    
            xmlrpc_env_init(&env);
    
            //registryP = xmlrpc_registry_new(&env);
    
           // xmlrpc_registry_add_method(
            //    &env, registryP, NULL, "sample.add", &sample_add, NULL);
    
            /* In the modern form of the Abyss API, we supply parameters in memory
               like a normal API.  We select the modern form by setting
               config_file_name to NULL:
            */
          //  serverparm.config_file_name = NULL;
           // serverparm.registryP        = registryP;
           // serverparm.port_number      = port;
           // serverparm.log_file_name    = "/tmp/xmlrpc_log";
    
           // printf("Running XML-RPC server...\n");
    
           // xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name));
    
            /* xmlrpc_server_abyss() never returns */
    
            return 0;
        }L;
       // serverparm.registryP        = registryP;
       // serverparm.port_number      = port;
       // serverparm.log_file_name    = "/tmp/xmlrpc_log";
    
       // printf("Running XML-RPC server...\n");
    
       // xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name));
    
        /* xmlrpc_server_abyss() never returns */
    
        return 0;
    }
    

    and this is the code the is used to load modules

    #ifndef RTLD_NOW
    
    #define RTLD_NOW DL_LAZY
    #endif   
    void* handle;
    char* error;
    
    
    handle=dlopen(mod->binary_file, RTLD_NOW); 
    
    if (!handle){
    LOG( " could not open file [%s]: %s\n",
        mod_cfg->binary_file, dlerror() );
    return 0;
    }
    
  • Basile Starynkevitch
    Basile Starynkevitch over 12 years
    but the original poster says that it returns NULL !
  • Tim Post
    Tim Post over 12 years
    @jørgensen Just a ping to let you know the question was edited. The OP did note that dlerror() returned NULL, but has since been edited for clarity.
  • yugr
    yugr almost 5 years
    This is a duplicate of another answer.