пятница, 5 сентября 2014 г.

Forward exported functions

При создании DLL в Windows необходимо определить точки входа в библиотеку. Чтобы имена были не декорированные (а именно такие стоит использовать, чтобы не зависеть от компоновщика — он от версии к версии делает совершенно разными) часто используется DEF-файл. Минимальный DEF-файл выглядит примерно так:
LIBRARY mydll

EXPORTS
	CreateSomethingCool @1

Документация MSDN однако умалчивает, что тут мы имеем возможность какие-то функции перенаправлять в другие DLL. Для этого надо написать что-то вроде:
LIBRARY mydll

EXPORTS
	CreateSomethingCool @1
	WriteConsole=Kernel32.WriteConsoleA

Теперь, если вызвать функцию WriteConsole из нашей библиотеки, то на самом деле вызовется функция WriteConsoleA из Kernel32.dll. Такой способ позволяет избежать явных зависимостей от других DLL и создания stub-функций. Указанная DLL будет подгружаться только, если кто-то вызовет конкретную экспортируемую функцию. Такого же результата можно добиться и с помощью директивы pragma:
#pragma comment(linker, "/export:WriteConsole=Kernel32.WriteConsoleA")

В прекрасной утилите Dependency Walker можно посмотреть на результат:
Тут видно, что вместо адреса функции WriteConsole указано перенаправление на функцию из Kernel32.dll.

Подобным образом можно обращаться и с экспортируемыми данными. Подробнее о том как это можно сделать можно почитать в статье по ссылке ниже.

Ссылки по теме:
  1. Exported functions that are really forwarders - Raymond Chen
  2. An In-Depth Look into the Win32 Portable Executable File Format, Part 2 - MSDN
  3. Forwarding data in a DLL - Stackoverflow.com

Комментировать в ВКонтакте