Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extend a dynamic linked shared library?

I'm new at C, so sorry for my lack of knowledge (my C-book here is really massive :)

I would like to extend a shared library (libcustomer.so) with closed source, but public known api.

Is something like this possible?

  1. rename libcustomer.so to liboldcustomer.so
  2. create an extended shared library libcustomer.so (so others implicitly use the extended one)
  3. link liboldcustomer.so into my extended libcustomer.so via -loldcustomer
  4. forward any not extra-implemented methods directly to the old "liboldcustomer.so"

I don't think it would work that way (the name is compiled into the .so, isn't it?). But what's the alternative?

For #4: is there a general way to do this, or do I have to write a method named like the old one and forward the call (how?)?

Because the original libcustomer.so (=liboldcustomer.so) can change from time to time, all that stuff should work dynamically.

For security reasons, our system has no LD_PRELOAD (otherwise I would take that :( ).

Think about extended validation-checks & some better NPE-handlings.

Thanks in advance for your help!

EDIT:

I'm just implementing my extension as shown in the answer, but I have one unhandled case at the moment:

How can I "proxy" the structs from the extended library?

For example I have this:

customer.h:

struct customer;

customer.c:

struct customer {
    int children:1;
    int age;
    struct house *house_config;
};

Now, in my customer-extension.c I am writing all the public methods form customer.c, but how do I "pass-thru" the structs?

Many thanks for your time & help!

like image 838
Martin L. Avatar asked Jan 21 '13 23:01

Martin L.


People also ask

Is a shared library a dynamic library?

Dynamic libraries (also called shared libraries) are linked into the program in two stages. First, during compile time, the linker verifies that all the symbols (again, functions, variables, and the like) required by the program, are either linked into the program or in one of its dynamic libraries.

Are dynamic libraries reusable?

Functions are blocks of code that are reusable throughout a program. Using them saves time, removing the need to rewrite code multiple times. Libraries, like functions also save time in that they make functiones reusable in multiple programs.

Is .so a dynamic library?

Shared libraries are also called dynamic libraries. These shared libraries are linked in at runtime by the dynamic linker available on the operating system. Shared libraries usually end with the . so extension — an example is libboost.5.6.so.

How does Ld so work?

When a program linked with shared libraries runs, program execution does not immediately start with that program's first statement. Instead, the operating system loads and executes the dynamic linker (usually called ld.so), which then scans the list of library names embedded in the executable.


1 Answers

So you have OldLib with

void func1();
int  func2();
... etc

The step 4 might look like creating another library with some static initialization.

Create NewLib with contents:

void your_func1();

void (*old_func1_ptr)() = NULL;
int  (*old_func2_ptr)() = NULL;

void func1()
{
    // in case you don't have static initializers, implement lazy loading
    if(!old_func1_ptr)
    {
       void* lib = dlopen("OldLibFileName.so", RTLD_NOW);
       old_func1_ptr = dlsym(lib, "func1");
    }

    old_func1_ptr();
}

int func2()
{
    return old_func2_ptr();
}

// gcc extension, static initializer - will be called on .so's load
// If this is not supported, then you should call this function
// manually after loading the NewLib.so in your program.
// If the user of OldLib.so is not _your_ program,
// then implement lazy-loading in func1, func2 etc. - check function pointers for being NULL
// and do the dlopen/dlsym calls there.
__attribute__((constructor))
void static_global_init()
{
   // use dlfcn.h
   void* lib = dlopen("OldLibFileName.so", RTLD_NOW);

   old_func1_ptr = dlsym(lib, "func1");
   ...
}

The static_global_init and all the func_ptr's can be autogenerated if you have some description of the old API. After the NewLib is created, you certainly can replace the OldLib.

like image 161
Viktor Latypov Avatar answered Oct 06 '22 13:10

Viktor Latypov