Как получить путь к библиотеке из ее дескриптора (macOS / iOS)? - PullRequest
0 голосов
/ 15 января 2019

У меня есть дескриптор динамической библиотеки (от использования dlopen()). Независимо от того, почему у меня нет доступа к тому, какой путь был указан для dlopen(), мне нужен путь для другой функции. Таким образом, мне нужно иметь возможность получить путь к библиотеке, используя ее дескриптор.

Я пытался использовать dladdr(), как и в других частях моего приложения, но в macOS / iOS вы не можете использовать его, чтобы найти путь к библиотеке, используя дескриптор только для библиотеки. работает с ручкой к символу в библиотеке. Я мог бы попытаться добавить «символ локатора» в библиотеку и выполнить задачу таким образом, но я бы предпочел этого не делать.

Я также пытался dlinfo() с RTLD_DI_LINKMAP, но это, по-видимому, недоступно в macOS / iOS.

1 Ответ

0 голосов
/ 15 января 2019

Я удивлен тем, как мало информации существует для этого. Многие решения там не были доступны на MacOS / iOS. Другие по-прежнему были только о том, чтобы получить путь к текущему исполняемому файлу, и не имели никакого отношения к дескриптору.

После ТОННА поиска я наконец-то наткнулся на некоторые ресурсы, в которых говорилось, что нужно перебрать все загруженные изображения, используя _dyld_image_count() и _dyld_get_image_name(). Сначала я решил против этого, так как это не казалось неоправданно медленным способом ведения дел.

В конце концов, я решил пройтись по всем загруженным изображениям, так как это было единственное реальное решение, с которым я столкнулся. Я гуглил по примерам и не смог найти ни одного учебника по теме. Однако я натолкнулся на библиотеку C ++ с открытым исходным кодом, которая реализовала эту функциональность (найдено здесь ).

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

Это окончательный код моего решения:

// NOT a thread safe way of doing things
NSString *pathFromHandle(void* handle)
{
    // Since we know the image we want will always be near the end of the list, start there and go backwards
    for (uint32_t i = (_dyld_image_count() - 1); i >= 0; i--)
    {
        const char* image_name = _dyld_get_image_name(i);

        // Why dlopen doesn't effect _dyld stuff: if an image is already loaded, it returns the existing handle.
        void* probe_handle = dlopen(image_name, RTLD_LAZY);
        dlclose(probe_handle);

        if (handle == probe_handle)
        {
            return [NSString stringWithUTF8String:image_name];
        }
    }


    return NULL;
}

Важно отметить, что это решение не является поточно-ориентированным, поскольку _dyld_image_count() и _dyld_get_image_name() по своей сути не являются поточно-ориентированными. Это означает, что любой другой поток может загрузить / выгрузить изображение и оказать негативное влияние на наш поиск.

Кроме того, ресурс , который я использовал, задавался вопросом, почему dlopen не оказал влияния на _dyld_image_count(). Это связано с тем, что если изображение уже загружено, dlopen не загружает новый экземпляр изображения, а скорее возвращает существующий дескриптор для него.

...