检测加载到单个程序中的两个ABI不兼容的共享库版本

时间:2021-10-13 07:00:09

I wrote a shared library with several incompatible versions. I changed SONAME, so they are called:

我写了一个包含几个不兼容版本的共享库。我改变了SONAME,所以他们被称为:

  • lib_mylib.so.1.0.0 (older library)
  • lib_mylib.so.1.0.0(旧库)

  • lib_mylib.so.2.0.0

There are some functions only in mylib.so.1, others are only in mylib.so.2 and many functions are common (but several has changed count of arguments)

mylib.so.1中只有一些函数,其他函数只在mylib.so.2中,很多函数都很常见(但有几个函数改变了参数的数量)

And I afraid that it is possible to link both versions of mylib into single application, for example when application itself is big and consists of many libraries. When application is rebuilt partially, there can be such situation:

我担心可以将mylib的两个版本链接到单个应用程序中,例如,当应用程序本身很大并且包含许多库时。当应用程序部分重建时,可能会出现这种情况:

  • Application
  • app_lib1.so (was built with mylib.so.1 - first version of my lib)
  • app_lib1.so(使用mylib.so.1构建 - 我的lib的第一个版本)

  • app_lib2.so (was rebuilt with mylib.so.2 - second version)
  • app_lib2.so(用mylib.so.2重建 - 第二版)

I already saw application with both versions loaded into it (ldd reports both).

我已经看到应用程序加载了两个版本(ldd报告两者)。

So, Is it possible to add some checking code to mylib.so.2 to detect that there are both versions of library already loaded and they have conflicting ABI/Interface. (I can't modify lib_mylib.so.1 to add something into it)

那么,是否可以向mylib.so.2添加一些检查代码,以检测是否已经加载了两个版本的库,并且它们具有冲突的ABI /接口。 (我不能修改lib_mylib.so.1来添加内容)

2 个解决方案

#1


3  

You can modify your version 2 library to resolve some version-1-specific symbol (dlsym(3)) during init and crash when found.

您可以修改版本2库以在init期间解析某些特定于版本1的符号(dlsym(3))并在找到时崩溃。

Example:

extern __attribute__((constructor)) void _version_check2()
{
    if (dlsym(RTLD_DEFAULT, "version_1_function"))
        abort();
}

A more graceful solution is to let version 2 library mimic the behaviour of version 1, but that introduces legacy code.

更优雅的解决方案是让版本2库模仿版本1的行为,但这会引入遗留代码。

EDIT

To be future proof, you can also introduce a static version variable and all function calls would check if it matches the current. Then in future versions you just need to change the value of that variable and crash if mismatch.

为了将来证明,您还可以引入静态版本变量,所有函数调用将检查它是否与当前匹配。然后在将来的版本中,您只需更改该变量的值,如果不匹配则崩溃。

EDIT 2

You can also call this function on every version 2 function so that sooner or later when version 1 gets loaded your app crashes.

您还可以在每个版本2函数上调用此函数,以便迟早版本1加载时您的应用程序崩溃。

#2


1  

You can parse /proc/self/maps to get the list of currently loaded objects.

您可以解析/ proc / self / maps以获取当前加载的对象列表。

#1


3  

You can modify your version 2 library to resolve some version-1-specific symbol (dlsym(3)) during init and crash when found.

您可以修改版本2库以在init期间解析某些特定于版本1的符号(dlsym(3))并在找到时崩溃。

Example:

extern __attribute__((constructor)) void _version_check2()
{
    if (dlsym(RTLD_DEFAULT, "version_1_function"))
        abort();
}

A more graceful solution is to let version 2 library mimic the behaviour of version 1, but that introduces legacy code.

更优雅的解决方案是让版本2库模仿版本1的行为,但这会引入遗留代码。

EDIT

To be future proof, you can also introduce a static version variable and all function calls would check if it matches the current. Then in future versions you just need to change the value of that variable and crash if mismatch.

为了将来证明,您还可以引入静态版本变量,所有函数调用将检查它是否与当前匹配。然后在将来的版本中,您只需更改该变量的值,如果不匹配则崩溃。

EDIT 2

You can also call this function on every version 2 function so that sooner or later when version 1 gets loaded your app crashes.

您还可以在每个版本2函数上调用此函数,以便迟早版本1加载时您的应用程序崩溃。

#2


1  

You can parse /proc/self/maps to get the list of currently loaded objects.

您可以解析/ proc / self / maps以获取当前加载的对象列表。