Following example covers API like dladdr, dlclose, dlerror, dlopen, dlsym and flags like RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, `RTLD_LOCAL, `RTLD_NODELETE`, `RTLD_NOLOAD`, RTLD_NEXT, RTLD_DEFAULT, etc.

  • At First Sight, This Might Look Lengthy & Alien, But If You Spend 5 Min, You Might Get What You Looking For.
  • I Struggle With Finding Dynamic Linking Example On Net When I Came Across Dynamic Linking Related Development. So I Wrote One Helping Post.

flags.c

  •  We will create binary flags out of flags.c & load both shared library libgetsum.so & `libsum.so` through dlopen with different configuration flags
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * Test Procedure :
 *
 * i. Create "libsum.so" from sum.c (kept in same folder).
 * 
 * gcc -o libgetsum.so -shared -fPIC getsum.c -D_GNU_SOURCE
 *
 * ii. Create "libgetsum.so" from sum.c (kept in same folder).
 * 
 * gcc -o libsum.so -shared -fPIC sum.c -D_GNU_SOURCE
 *
 * iii. Create "flags" binary from flags.c file
 *
 * gcc -o flags flags.c -ldl -D_GNU_SOURCE
 *
 */

/*
 * Verification Method:
 *
 * [libsum.so]             : Loaded successfully
 * [dlsym()]               : Executed successfully
 * sum(0,0)                : 1
 * Error relocating /home/vishal/libgetsum.so: sum: symbol not found
 * [libsum.so]             : Closed successfully
 * [libsum.so]             : Loaded again successfully
 * [libgetsum.so]          : Loaded again successfully
 * [dlsym()]               : Executed successfully
 * getsum(4, 5)            : 11
 * [dlsym()]               : Executed successfully
 * func()                  : Executed Successfully From [libgetsum.so]
 * [dladdr()]              : Executed successfully
 * Function                : funcXYZ
 * Shared Lib              : /home/vishal/libgetsum.so
 *
 */

#include 
#include 
#include 
#include 


/*Please Provide Absolute Path Of Both Libs */
#define LIB_1   "Absolute_path_to_libsum.so"
#define LIB_2   "Absolute_path_to_libgetsum.so"


int main(int argc, char **argv)
{
    /*------------------- PASS 1 : Loading Shared Lib 1  -----------------*/
    void *lib1 = dlopen(LIB_1, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE );
    if (!lib1) {
        dprintf(1, "[libsum.so]     : Error in finding the library : PASS 1\n");
        fputs(dlerror(), stderr);
        exit(1);
    }
    else{
        dprintf(1, "[libsum.so]     : Loaded successfully \n");
    }
    /*---------------------------------------------------------------------*/


    /*------------------ PASS 2 : Finding Symbol & Execute it--------------*/
    int (*sum)(int , int) = (int (*)(int , int))dlsym(lib1, "sum");
    char *error = dlerror();
    if (error != NULL)  {
        dprintf(1, "[dlsym()]       : Error : PASS 2\n");
        fputs(error, stderr);
        exit(1);
    }
    else{
        dprintf(1,"[dlsym()]        : Executed successfully\n");
        printf("sum(0,0)        : %d \n", (*sum)(0, 0));
    }
    /*---------------------------------------------------------------------*/



    /*------------------ PASS 3 : Loading Shared Lib 2  -------------------*/
    void *lib2 = dlopen(LIB_2, RTLD_NOW);
    if (!lib2) {
        fputs(dlerror(), stderr);
        if( dlclose(lib1) == 0 ){   /* Closing Shared Lib 1 */
            dprintf(1, "\n[libsum.so]       : Closed successfully \n");
        }
        else{
            dprintf(1, "\n[libsum.so]       : Error in closing : PASS 3 \n");
        }
    }
    else{
        dprintf(1, "[libgetsum.so]      : Loaded successfully \n");
    }
    /*---------------------------------------------------------------------*/


    /*----------------- PASS 4 : Loading Shared Lib 1 Again ---------------*/
    lib1 = dlopen(LIB_1, RTLD_NOW | RTLD_NOLOAD | RTLD_GLOBAL );
    if (!lib1) {
        dprintf(1, "[libsum.so]     : Error in finding the library : PASS 4\n");
        fputs(dlerror(), stderr);
        exit(1);
    }
    else{
        dprintf(1, "[libsum.so]     : Loaded again successfully \n");
    }
    /*---------------------------------------------------------------------*/


    /*----------------- PASS 5 : Loading Shared Lib 2 Again ---------------*/
    lib2 = dlopen(LIB_2, RTLD_NOW  | RTLD_GLOBAL );
    if (!lib2) {
        dprintf(1, "[libgetsum.so]      : Error in finding the library : PASS 5\n");
        fputs(dlerror(), stderr);
        exit(1);
    }
    else{
        dprintf(1, "[libgetsum.so]      : Loaded again successfully \n");
    }
    /*---------------------------------------------------------------------*/


    /*------------------ PASS 6 : Finding Symbol & Execute it--------------*/
    int (*getsum)(int , int) = (int (*)(int , int))dlsym(RTLD_DEFAULT, "getsum");
    error = dlerror();
    if (error != NULL)  {
        dprintf(1, "[dlsym()]       : Error : PASS 6\n");
        fputs(error, stderr);
        exit(1);
    }
    else{
        dprintf(1,"[dlsym()]        : Executed successfully\n");
        printf("getsum(4, 5)        : %d\n", (*getsum)(4, 5));
    }
    /*---------------------------------------------------------------------*/


    /*------------------ PASS 7 : Finding Symbol & Execute it--------------*/
    void (*func)(void) = (void (*)(void))dlsym( lib2, "funcXYZ");
    error = dlerror();
    if (error != NULL)  {
        dprintf(1, "[dlsym()]       : Error : PASS 7\n");
        fputs(error, stderr);
        exit(1);
    }
    else{
        dprintf(1,"[dlsym()]        : Executed successfully\n");
        printf("func()          : ");
        (*func)();
    }
    /*---------------------------------------------------------------------*/


    /*------------- PASS 8 : Resolving Function Name By Address -----------*/
    Dl_info  DlInfo;

    if( dladdr(func, &DlInfo) != 0 ){
        dprintf(1, "[dladdr()]      : Executed successfully  \n");
        dprintf(1, "Function        : %s  \n", DlInfo.dli_sname);
        dprintf(1, "Shared Lib      : %s  \n", DlInfo.dli_fname);
    }
    else{
        dprintf(1, "[dladdr()]              : Error : PASS 8\n");
        exit(1);
    }
    /*---------------------------------------------------------------------*/

    dlclose(lib1);
    dlclose(lib2);

    return 0;
}

sum.c

  • We will generate  libsum.so out of this file & load  libsum.so from flags.c through dlopen
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include 
#include 

int sum(int a, int b)
{
        static int i=0;
        i++;
        return a + b + i;
}

void funcXYZ()
{
        static void (*fptr)(void) = NULL;

        /* Come here only first time */
        if (fptr == NULL) {
                fptr = (void (*)(void))dlsym(RTLD_NEXT, "funcXYZ");
                if (fptr == NULL) {
                        printf("dlsym: %s\n", dlerror());
                        return ;
                }
        }

        (*fptr)();
}

getsum.c

  • We will generate  libgetsum.so out of this file & load  libgetsum.so from flags.c through dlopen
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include

extern int sum(int,int);

int getsum(int a, int b)
{
        return sum(a,b);
}

void funcXYZ()
{
        printf("Executed Successfully From [libgetsum.so]\n");
}