Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dyanamic library linking by RTLD_LAZY

I am trying to find the differance between RTLD_NOW and RTLD_LAZY flags. My query is why RTLD_LAZY loading the library whose function I've never referanced.

I have created a dlrun.c file

#include "stdio.h"
#include "dlfcn.h"

main()
{
  void * ptr;
  void (*fptr)(void);
  printf("\nMy ID is- %d \n",getpid());
  getchar();
  ptr = dlopen("./fun5.so", RTLD_NOW);
  if(ptr==NULL)
    printf("failed to open fun5.so");
  else
  {
    printf("I got fun5.so");
    fptr= dlsym(ptr,"fun5");
    getchar();
    fptr();
    printf("end of fun5");
    dlclose(ptr);
  }
}

the next file fun5.c as

#include "stdio.h"

void fun2(void);
void fun1(void);

fun5()
{
  printf("I am in fun5");
  getchar();
  fun1();
}

fun()
{
  getchar(); 
  fun2();
}

other file fun1.c is

#include "stdio.h"

fun1()
{
  printf("I am in fun1");
  getchar();
}  

and file fun2.c is

#include "stdio.h"

fun2()
{
  printf("I am in fun2");
  getchar();
}

then I use commands

gcc -c -fPIC -o fun1.o fun1.c
gcc -c -fPIC -o fun2.o fun2.c
gcc -c -fPIC -o fun5.o fun5.c
gcc -shared -o fun1.so fun1.o
gcc -shared -o fun2.so fun2.o
gcc -shared -o fun5.so fun5.o ./fun1.so ./fun2.so
gcc dlrun.c -o run -ldl
./run

now I want to check which libraries are loaded by

cd /proc/<pid>
vi maps

Here it looks that before fun5.so calling no nonstansard libray is loaded and after calling fun5 function all fun5.so,fun1.so and fun.2.so are loaded as per expectation.Now if I replace RTLD_NOW by RTLD_LAZY then only fun5.so and fun1.so should be loaded because I have never called fun() and fun2() , but actually fun2.so is also loading.so where am I wrong? Am I wrong at creating fun5.so? if so then how should I create it?

Thanks

like image 509
user3452214 Avatar asked Mar 23 '14 13:03

user3452214


People also ask

How are dynamic libraries linked?

Dynamic libraries are linked during the execution of the final executable. Only the name of the dynamic library is placed in the final executable. The actual linking happens during runtime, when both executable and library are placed in the main memory.

How is dynamic linking implemented?

Dynamic linking from Assembler language programs in IBM OS/360 and its successors is done typically using a LINK macro instruction containing a Supervisor Call instruction that activates the operating system routines that makes the library module to be linked available to the program.

What happens if Dlopen is called twice?

If the same library is loaded again with dlopen(), the same file handle is returned. The dl library maintains reference counts for library handles, so a dynamic library is not deallocated until dlclose() has been called on it as many times as dlopen() has succeeded on it.

How does dynamic library loading work?

Dynamic loading is a mechanism by which a computer program can, at run time, load a library (or other binary) into memory, retrieve the addresses of functions and variables contained in the library, execute those functions or access those variables, and unload the library from memory.


2 Answers

The following example should make it very clear:

libtest.so:

void bar();

void foo()
{
    bar();
}

_

$> nm libtest.so
000085d0 a _DYNAMIC
000086b0 a _GLOBAL_OFFSET_TABLE_
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
         w _Jv_RegisterClasses
000005c0 r __FRAME_END__
000085cc d __JCR_END__
000085cc d __JCR_LIST__
000086e0 d __TMC_END__
000086e4 B __bss_end__
000086e0 B __bss_start
000086e0 B __bss_start__
         w __cxa_finalize@@GLIBC_2.4
000004f8 t __do_global_dtors_aux
000085c8 t __do_global_dtors_aux_fini_array_entry
000086dc d __dso_handle
000086e4 B __end__
000085c4 t __frame_dummy_init_array_entry
         w __gmon_start__
000086e4 B _bss_end__
000086e0 D _edata
000086e4 B _end
000005b8 T _fini
000003e0 T _init
         U bar
00000424 t call_weak_fn
000086e0 b completed.8847
00000448 t deregister_tm_clones
000005a8 T foo
00000560 t frame_dummy
0000049c t register_tm_clones

main.c (flag == RTLD_LAZY):

#include <dlfcn.h>
#include <stdio.h>

int
main(int argc, char **argv)
{
    void *lib = dlopen("./libtest.so", RTLD_LAZY);
    if (!lib) {
        printf("error: %s\n", dlerror());
        return 0;
    }
    int (*a)() = dlsym(lib, "foo");
    printf("a: %p\n", a);
    (*a)();

    dlclose(lib);
    return 1;
}

$> ./main.c
a: 0xb6e225a8
./main: symbol lookup error: ./libtest.so: undefined symbol: bar

main.c (flag == RTLD_NOW):

#include <dlfcn.h>
#include <stdio.h>

int
main(int argc, char **argv)
{
    void *lib = dlopen("./libtest.so", RTLD_NOW);
    if (!lib) {
        printf("error: %s\n", dlerror());
        return 0;
    }
    int (*a)() = dlsym(lib, "foo");
    printf("a: %p\n", a);
    (*a)();

    dlclose(lib);
    return 1;
}
$> ./main.c
error: ./libtest.so: undefined symbol: bar
like image 176
fliX Avatar answered Sep 18 '22 12:09

fliX


RTLD_LAZY actually means resolve symbols lazily, not load libraries lazily. fun5.so depends on both of these libraries so they will be loaded when fun5.so is loaded.

The line:

gcc -shared -o fun5.so fun5.o ./fun1.so ./fun2.so

tells us that fun5.so explicitly depends on fun1.so and fun2.so, which is why you're seeing this behaviour.

like image 39
Petesh Avatar answered Sep 20 '22 12:09

Petesh