DLL

eXeL@B DVD

Материал из Справочник исследователя программ

(Перенаправлено с Dll)
Перейти к: навигация, поиск

DLL (англ. Dynamic-link library — библиотека динамической компоновки) — понятие операционных систем Microsoft Windows и IBM OS/2; динамическая библиотека, позволяющая многократное применение различными программными приложениями. K DLL относятся также элементы управления ActiveX и драйверы. В мире UNIX аналогичные функции выполняют т. н. shared objects («разделяемые объекты»).

Формат файлов DLL придерживается тех же соглашений, что и формат исполняемых файлов, сочетая код, таблицы и ресурсы.

Содержание

Цели введения DLL

Первоначально предполагалось, что введение DLL позволит эффективно организовать память и дисковое пространство, используя только один экземпляр библиотечного модуля для различных приложений. Это было особенно важно для ранних версий Microsoft Windows с жёсткими ограничениями по памяти.

Далее, предполагалось улучшить эффективность разработок и использования системных средств за счёт модульности. Замена DLL-программ с одной версии на другую должна была позволить независимо наращивать систему, не затрагивая приложений. Кроме того, библиотеки DLL могли использоваться разнотипными приложениями — например, Microsoft Office, Microsoft Visual Studio и т. п.

В дальнейшем идея модульности выросла в концепцию COM.

Фактически, полных преимуществ от внедрения DLL получить не удалось по причине явления, называемого DLL hell («ад DLL»). DLL Hell возникает, когда несколько приложений требуют одновременно различные, не полностью совместимые, версии DLL-библиотек, что приводит к сбоям в этих приложениях. Когда система выросла до определённых размеров, количество DLL стало превышать многие тысячи, не все из них обладали полной надёжностью и совместимостью, и конфликты типа DLL Hell стали возникать очень часто, резко понижая общую надёжность системы. Поздние версии Microsoft Windows стали разрешать параллельное использование разных версий DLL, что свело на нет преимущества изначального принципа модульности. Использование разных версий Dll стало возможным благодаря файлу манифеста (manifest), который хранится в ресурсах приложения или в виде отдельного файла в одном с приложением каталоге.

Примеры использования DLL в разных языках

Экспорт в DLL

Delphi

library Example;

{ Производим некие действия и возвращаем результат }
function AddNumbers(a, b: Double): Double; cdecl;
begin
  AddNumbers := a + b
end;

{ Эта функция экспортируется }
exports
  AddNumbers;

{ Инициализатор DLL, аналог функции main() в языках C и C++ }
begin
end.

C и C++

#include <windows.h>

#define DLLEXPORT extern "C" __declspec(dllexport)
                // extern "C" обозначает использование простой генерации
                // сигнатуры функции (в стиле языка С) при получении объектных
                // файлов. В частности, это запрещает компилятору C++
                // производить "декорацию" (или "украшение") имени функции
                // дополнительными символами при экспорте в DLL

/* Эта функция экспортируется */
DLLEXPORT double AddNumbers(double a, double b)
  // Прототип функции (функция без тела). По данной заявленной сигнатуре функции поиск её тела
  // при линковке будет произведён ниже или в другом бинарном файле 
;

/* Инициализационная функция DLL, аналог main() */
bool APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
  return TRUE;
}

/* 
   Тело (реализация) заявленного выше прототипа функции.
   Производит некие действия и возвращает результат
 */
DLLEXPORT double AddNumbers(double a, double b)
{
  return a + b;
}

Импорт из DLL

Delphi

program Example;
{$APPTYPE CONSOLE}

{ Указываем, что функция находится в DLL }
function AddNumbers(a, b: Double): Double; cdecl; external 'Example.dll';

{ Используем функцию как обычно }
var result: Double;
begin
  result := AddNumbers(1, 2);
  Writeln('The result was: ', result)
end.

C и C++

#include <stdio.h>

/*
 * Указываем, что тело функции находится в другом файле.
 * Не забыть про объектный модуль DLL при линковке!
 */
extern "C" __declspec(dllimport)double AddNumbers(double a, double b);

/* Используем функцию как обычно */
int
main(int argc, char **argv)
{
    double result = AddNumbers(1, 2);
    printf("The result was: %f\n", result);
    return 0;
}

Подгрузка и импорт из DLL во время работы

Delphi

program Example;
{$APPTYPE CONSOLE}

var result: Double;
    LibHandle: Hmodule;
    AddNumbers: function(a, b: Double): Double;
begin
  LibHandle := LoadLibrary('Example.dll'); // загружаем DLL
  if LibHandle <> 0 then
    begin
      @AddNumbers := GetProcAddress(LibHandle, 'AddNumbers'); // запоминаем адрес
                                                              // необходимой функции
      if @AddNumbers <> nil then
        begin
          result := AddNumbers(1, 2);       // используем функцию
          Writeln('The result was: ', result);
        end;
      FreeLibrary(LibHandle);               // выгружаем DLL
    end;
end.

C и C++

#include <windows.h>
#include <stdio.h>

/*
 * Тип используемой функции
 * (комбинация типов параметры и возвращаемого значения)
 */
typedef double (*importFunction)(double, double);

int
main(int argc, char **argv)
{
    importFunction addNumbers;
    double result;

    /* Загружаем DLL в память */
    HINSTANCE hinstLib = LoadLibrary("Example.dll");
    if (hinstLib == NULL) {
        printf("ERROR: unable to load DLL\n");
        return 1;
    }

    /* Получаем указатель на функцию */
    addNumbers = (importFunction)GetProcAddress(hinstLib, "AddNumbers");
    if (addNumbers == NULL) {
        printf("ERROR: unable to find DLL function\n");
        return 1;
    }

    /* Вызываем функцию через указатель */
    result = addNumbers(1, 2);

    /*
     * Выгружаем DLL (в принципе, это будет сделано
     * автоматически при выходе из программы)
     */
    FreeLibrary(hinstLib);

    /* Отображаем результат */
    printf("The result was: %f\n", result);

    return 0;
}

Уязвимости в механизмах DLL

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

Ссылки

Оригинальный текст статьи на Википедии

Написание и использование DLL в различных средах

Win32 DLL

Источник — «https://exelab.ru/faq/DLL»