Динамическая загрузка пары отсутствующих функций

#macos #dyld #wcsdup

#macos #dyld #wcsdup

Вопрос:

У меня есть двоичный файл, рекламируемый как работающий в Mac OS X 10.6, но он пытается связать wcsdup() функцию, которая была добавлена только в 10.7. Это выдержка из отчета об ошибке, сгенерированного при запуске в версии 10.6.8:

Процесс: paradiseperfectboatrescue [149]
…
Тип кода: X86-64 (собственный)
Родительский процесс: launchd [86]
…
Версия операционной системы: Mac OS X 10.6.8 (10K549)
…
Сообщение об ошибке Dyld:
 Символ не найден: _wcsdup
 Ссылка из: .../Paradise Perfect Boat Rescue.app/Contents/macOS/paradiseperfectboatrescue
 Ожидается в: /usr/lib/libSystem.B.dylib
…

Разработчик по той или иной причине не устранил проблему, о чем сообщалось ~ 6 месяцев назад. Мне было интересно, есть ли какая-либо надежда обойти проблему с помощью программных инструментов. В частности, можно ли было бы указать dyld получать wcsdup() из другого места? Это простая функция, и, предполагая, что это единственная отсутствующая функция, ее можно легко реализовать. Вот реализация, которую я бы использовал, если бы была возможность:

 #include <wchar.h>
#include <string.h>
#include <stdlib.h>

wchar_t* wcsdup (const wchar_t *s)
{
  size_t len = wcslen(s)   1;
  len *= sizeof(wchar_t);
  wchar_t *d = malloc(len);

  if (d)
    return memcpy(d, s, len);
  else
    return 0;
}
  

Я использовал DYLD_LIBRARY_PATH в других обстоятельствах, но тогда я хотел помочь dyld найти целые библиотеки, которые в противном случае были пропущены. На этот раз моя цель — не предоставить целую новую библиотеку, а дополнить существующую несколькими функциями, которые используют функции из дополняемой библиотеки. Возможно ли сказать dyld, чтобы он это сделал?

Ответ №1:

Я думаю, вы хотите DYLD_INSERT_LIBRARIES посмотреть здесь: http://tlrobinson.net/blog/2007/12/overriding-library-functions-in-mac-os-x-the-easy-way-dyld_insert_libraries/

Это как LD_PRELOAD в Linux … вместо того, чтобы предоставлять список путей к библиотекам для проверки библиотек, которые, как известно, нужны исполняемому файлу, мы загружаем функции из определенного файла и предотвращаем их поиск в другом месте.

Комментарии:

1. Благодаря инструкциям со страницы, на которую вы ссылаетесь, программа проходит динамическую загрузку и начинает выполняться. Это приведет к взаимоблокировке чуть позже, но это явно не связано (и мне, вероятно, следует отказаться от идеи запуска на 10.6 программы, которая не была скомпилирована для нее).

Ответ №2:

Для записи на случай, если страница, на которую ссылается ответ Джона, исчезнет, вот что я сделал:

$ gcc -Wall -o wcsdup_ov.dylib -dynamiclib w.c 
$ export DYLD_FORCE_FLAT_NAMESPACE=1
$ export DYLD_INSERT_LIBRARIES=$HOME/wcsdup_ov.dylib
$ open ~/Desktop/Paradise Perfect Boat Rescue.app

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