Загрузить общую библиотеку для другой общей библиотеки - PullRequest
0 голосов
/ 14 ноября 2018

Я работаю над приложением обновления, которое должно быть в состоянии работать в существующей системе, а также запущено другим приложением в этой существующей системе.

Я использую общую библиотеку, которая сама использует OpenSSL, ноне связывался с этимРанее мое приложение обновлений связывалось с OpenSSL, чтобы обойти это.Но теперь я больше не могу ссылаться на OpenSSL из-за двоичной несовместимости.Теперь, когда мое приложение запускается в существующей системе, я получаю ошибку undefined symbol, потому что OpenSSL не загружен.Обратите внимание, что у меня нет возможности загрузить его через LD_PRELOAD, потому что я не могу изменить приложение, которое запускает мое приложение обновления.

Я думал о загрузке OpenSSL через dlopen, надеясь, что общая библиотекабыть в состоянии использовать это.Но разделяемая библиотека использует OpenSSL в конструкторе C (__attribute__((constructor (101))) void myConstructor()), и даже если я вызову dlopen в другом конструкторе с более высоким приоритетом, динамический загрузчик уже, похоже, уже искал (и не смог) OpenSSL.Мой конструктор даже не выполняется.

LD_BIND_NOW не установлен, поэтому мне интересно, почему ошибка undefined symbol возникает до вызова моего конструктора.

1 Ответ

0 голосов
/ 16 ноября 2018

Я сам нашел решение.

Проблема заключалась в том, что разделяемые библиотеки инициализировались (т.е. вызывались конструкторы C) перед основным приложением.Вы можете видеть порядок, когда устанавливаете переменную окружения LD_DEBUG=libs.Так что я сам создал общую библиотеку.Я связал эту библиотеку исправлений после библиотеки с ошибками (-lbuggy -lfix), потому что инициализация примерно (я не очень понимаю правила.) Происходит в обратном порядке загрузки.

Теперь я смог загрузить OpenSSL внутриконструктор C моей библиотеки исправлений, подобный этому:

void *p = dlopen("libssl.so.1.0.0", RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE);
if(p)
  dlclose(p);

Флаг RTLD_GLOBAL гарантирует, что OpenSSL также может использоваться другими библиотеками.Флаг RTLD_NODELETE гарантирует, что библиотека не выгружена в dlclose.

Примечание. Когда мое приложение обновления запускается в более новой системе с OpenSSL 1.1 и совместно используемой библиотекой, которая правильно связывается с OpenSSL, загружается libssl.so.1.0.0 тихо завершится сбоем, потому что старая версия OpenSSL отсутствует в этой системе (встроенная система, необходимо сэкономить место на диске).Если OpenSSL 1.0 все еще присутствует, это может быть проблемой.

...