#linux #dll #object #constructor #shared
#linux #dll #объект #constructor #общий
Вопрос:
В Windows конструктору DllMain передается несколько аргументов:
BOOL WINAPI DllMain(
__in HINSTANCE hinstDLL,
__in DWORD fdwReason,
__in LPVOID lpvReserved
);
Из hinstDLL я могу получить полное имя файла самой библиотеки DLL, используя GetModuleFileName():
LPTSTR str = new TCHAR[256];
int libNameLength = GetModuleFileName(hinstDLL, str, 256);
delete[] str;
В приведенном выше примере str теперь содержит полное имя только что загруженной DLL, например, C:WindowsSystem32MyFile.dll.
В Linux конструктору общего объекта не передаются аргументы:
void `__attribute__` ((constructor)) on_load(void);
Как мне получить полное имя библиотеки DLL в этом случае? Дополнительная оценка, если ваше решение работает и на Mac. 🙂
Комментарии:
1. Я не знаю, есть ли хороший способ. Мой вопрос в подобных ситуациях: «Почему вы хотите знать?». Отступив на уровень назад, вы можете обнаружить, что есть путь к вашей реальной цели, не делая шага, который в данный момент блокирует вас.
2. Хороший вопрос. Я хочу знать, потому что я разрабатываю CSP и модуль PKCS # 11 (DLL-файлы), оба из которых должны проверять свою целостность при загрузке. Оба DLL-файла загружаются ОС, поэтому моей точкой входа является конструктор. В настоящее время лучшая идея, которая у меня есть для проверки целостности DLL-файла, — это вычислить хэш DLL-файла в конструкторе, а затем отправить этот хэш на центральный сервер, который может проверить правильность хэша. Однако мне нужно имя файла DLL, чтобы иметь возможность вычислить хэш.
Ответ №1:
Я думаю, dladdr
функция может делать то, что вы хотите. Со страницы руководства:
Функция dladdr() принимает указатель на функцию и пытается разрешить имя и файл, в котором он находится. Информация хранится в
Dl_info
структуре:typedef struct { const char *dli_fname; /* Pathname of shared object that contains address */ void *dli_fbase; /* Address at which shared object is loaded */ const char *dli_sname; /* Name of nearest symbol with address lower than addr */ void *dli_saddr; /* Exact address of symbol named in dli_sname */ } Dl_info;
Если не удалось найти символ, соответствующий addr, то
dli_sname
и
dli_saddr
имеют значениеNULL
.
dladdr()
возвращает 0 при ошибке и ненулевое значение при успешном выполнении.
Итак, вы просто даете ему указатель на функцию (например, адрес самого конструктора), и он выдаст вам имя файла и кучу другой информации. Вот несколько примеров кода:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
__attribute__((constructor))
void on_load(void) {
Dl_info dl_info;
dladdr(on_load, amp;dl_info);
fprintf(stderr, "module %s loadedn", dl_info.dli_fname);
}
РЕДАКТИРОВАТЬ: Похоже, что эта функция существует и в OS X с той же семантикой.
Комментарии:
1. Да, я так счастлив, что способ, о котором мы оба подумали, не является правильным ответом. 🙂
2. Этот метод не работает на Android:
dli_fname
содержит только имя файла, а не полный путь.
Ответ №2:
Один в высшей степени уродливый и ужасный способ сделать это — просмотреть /proc/pid /maps и найти отображение, которое охватывает адрес выполняемой on_load
функции.
Комментарии:
1. Я начал идти по этому пути вчера, и я еще не отбросил его полностью , потому что на данный момент это единственное жизнеспособное решение, которое я знаю. Хотя у меня от этого тоже мурашки бегут по спине.