Extend a dynamic linked shared library?

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-13 11:50:25

问题


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!


回答1:


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.



来源:https://stackoverflow.com/questions/14448756/extend-a-dynamic-linked-shared-library

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!