3

Я попытался сформулировать проблему абстрактным образом, но в любом случае я подробно расскажу о фактических библиотеках в конце.Сложная динамическая и статическая связь с дубликатами (надстройки Firefox, WebRTC и VP8)

Динамическая библиотека Addon статический связана с другой библиотекой WebRTC, которая имеет некоторый код в сборке и этот код связан в WebRTC, как объектные файлы вместе с собственными объектными файлами WebRTC «s. Позволяет называть этот код сборки VP8. Функции VP8 отмечены extern внутри WebRTC. Некоторая функция Encode() от Addon вызывает функции WebRTC, которая в конечном итоге вызывает функции от VP8.

Теперь приложение Firefox который собирается загрузить библиотеку Addon довольно сложна и имеет свою собственную версию (средства статически скомпонованный) библиотеки WebRTC (назовем его WebRTC2), но более старый.

Итак, вот проблема: если вызов Encode() производится из приложения Firefox, WebRTC функции вызываются (не WebRTC2, который является правильным) НО когда WebRTC пытается вызвать VP8 функции, они вызываются из версия WebRTC2 (означает версию приложения WebRTC), но не от WebRTC.

Есть ли способ заставить WebRTC звонить только из местной копии VP8?

Применение Firefox является браузер Firefox, WebRTC библиотека WebRTC, VP8 библиотека VP8 кодек (внутри WebRTC) и Addon мой Firefox C++ дополнения.

ОБНОВЛЕНИЕ - Подробное описание

Вот «unabstract» Описание проблемы: Так есть C++ XPCOM надстройка, которая статически связана с последней версией библиотеки WebRTC. В какой-то момент внутри надстройки выполняется вызов для кодирования кадра (метод Encode из VP8Encoder), и он постоянно сбой в Firefox, а также продолжает хорошо работать на тестовых программах с использованием gtest framework.

Проблема в том, что в какой-то момент внутри WebRTC имеется код сборки VP8, который вызывается для кодирования, а функции этого кода сборки объявляются как extern в файлах реализации. Фактически, он падает на функцию vp8_intra_pred_y_ve_sse2. Я сравнил три ассемблерных кода этой функции: один из моей версии WebRTC (используется в дополнении), второй - где отладчик разбился, а третий - из исходного кода WebRTC Mozilla.

Оказалось, что по какой-то странной причине код Mozilla вызывается вместо WebRTC надстройки (у них обоих одинаковые имена), а так как код WebRTC от Mozilla устарел, он вылетает с EXC_BAD_ACCESS.

+0

На самом деле, попробуйте «вырезать» материал. Было бы проще понять, что вместо имен однобуквенных имен вам нужно отслеживать фактические имена (я понял это в конце, но не имею ответа на предложение). Кроме того, вы опустили множество подробностей, например, как материал создается (связан) и какой механизм загрузит материал (загрузчик Windows DLL, ld и т. Д.), Все из которых могут/будут иметь значение ... Кроме того, это не так 'На самом деле, похоже, проблема с firefox-addon, но больше похожа на проблему с общим динамическим загрузчиком ... – nmaier

+0

Да, я согласен, что это общая проблема. Тем не менее, я обновил описание с подробностями. – peetonn

ответ

1

Это, вероятно, не будет существенно помочь вам, но так как никто не ответил, вот я иду ...

Вы не упомянули, если вы работаете на Linux, Windows, или что-то остальное. Мой ответ для Linux. Я считаю, что Windows загружает динамические библиотеки по-разному.

Я думаю, что вы статически связаны с интерфейсами заглушки библиотеки WebRTC, а эти интерфейсы-заглушки динамически связаны с реальной реализацией, а затем получают первый экземпляр библиотеки WebRTC, загружаемой в firefox, а не второй , Убедитесь, что вы действительно связываетесь со статически скомпилированной версией библиотеки WebRTC.

Человек страница Linux dlopen(3) имеет интересный флаг в списке, который, кажется, что это поможет если ваша библиотека была одна загрузки библиотеки WebRTC:

void *dlopen(const char *filename, int flag); 

dlopen()

The function dlopen() loads the dynamic library file named by the null- 
    terminated string filename and returns an opaque "handle" for the 
    dynamic library. [...] 

    RTLD_DEEPBIND (since glibc 2.3.4) 

     Place the lookup scope of the symbols in this library ahead of 
     the global scope. This means that a self-contained library will 
     use its own symbols in preference to global symbols with the 
     same name contained in libraries that have already been loaded. 
     This flag is not specified in POSIX.1-2001. 

К сожалению, firefox - это тот, который загружает вашу библиотеку.

Если ваша библиотека динамически связана с WebRTC (что похоже), и вы явно загрузили библиотеку WebRTC, которую хотите использовать с dl_open(), с флагом RTLD_DEEPBIND, чем это решит вашу проблему.

Это не поможет вам много, так как его не ваш код, который связывания vp8_intra_pred_y_ve_sse2, но его стоит отметить, что НКУ также имеет функцию dlsym() которая может занять несколько специальных флагов:

void *dlsym(void *handle, const char *symbol); 

dlsym()

The function dlsym() takes a "handle" of a dynamic library returned by 
    dlopen() and the null-terminated symbol name, returning the address 
    where that symbol is loaded into memory. [...] 

    There are two special pseudo-handles, RTLD_DEFAULT and RTLD_NEXT. The 
    former will find the first occurrence of the desired symbol using the 
    default library search order. The latter will find the next occurrence 
    of a function in the search order after the current library. This 
    allows one to provide a wrapper around a function in another shared 
    library. 

Вы можете использовать это в вашем коде, по крайней мере, отлаживать, что происходит при наличии его распечатать ворота значения, которые он получает для поиска vp8_intra_pred_y_ve_sse2.

Наконец, тот же человек, страница отмечает, что Linux имеет dlvsm(), который принимает версии строковый аргумент, а также, что позволяет код XPCOM указать, какую версию функции, которую он хочет:

#define _GNU_SOURCE   /* See feature_test_macros(7) */ 
    #include <dlfcn.h> 

    void *dlvsym(void *handle, char *symbol, char *version); 

Если бы это было , и я был вынужден динамически связывать вещи, я бы пошел с грубой силой подхода. Перейдите в библиотеки и измените имена функций (в обеих библиотеках). Это не изящно, и это будет головная боль всякий раз, когда выходит новая версия любой библиотеки, но ее простая и прямая.