Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Подземелье Магов
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  13:33[Войти] | [Зарегистрироваться]

Несколько слов о загрузке DLL

Миша Басов
дата публикации 07-04-2003 15:29

Несколько слов о загрузке DLL

Здравствуйте, коллеги! Поводом для написания этой статьи стало прочтение статьи Криса Касперски "Паковать или не паковать?".

Вкратце содержание статьи (дается в произвольном виде, со своими коментариями).

Все исполняемые модули (EXE и DLL) грузятся в память Windows(NT/2000/XP) следующим образом (я оставил только важные для нас пункты)
Загрузка первой копии приложения:
  • Прочитать служебную информацию из файла.
  • Спроецировать в память все секции файла с защитой PAGE_EXECUTE_WRITECOPY(ну, кроме данных)
  • Некоторые дополнительные приготовления (о них речь и пойдет в статье)
  • Модуль готов.
Загрузка всех последующих копий приложения:
  • Прочитать служебную информацию из файла.
  • Спроецировать в память все секции файла с защитой PAGE_EXECUTE_WRITECOPY(ну кроме данных...), здесь система ведет себя несколько по-другому, нежели при первой загрузке, поэтому я выделил ее в другой блок, но это тонкости.
  • Некоторые дополнительные приготовления(о них речь и пойдет в статье)
  • Модуль готов.

Отличий, вроде бы, никаких? Но (!!!) пункт 2 говорит, что память выделяется всем копиям одна и та же(!!!). Таково свойство проецируемых файлов(см. Help. Topic: CreateFileMapping, OpenFileMapping, MapViewOfFile …).
"А как же данные каждого приложения, которые не зависимы от других приложений?"- спросите Вы. А для этого и стоит защита. Как только программа пытается писать что-то в память, система делает копию этой страницы, ставит ей соответствующую защиту, и далее это приложение работает со своей (измененной) страницей, а все остальные с общей. Зачем так сложно? Из экономии памяти и увеличения быстродействия, ведь когда идет SWAP памяти, не измененные страницы система просто удаляет (ведь они остались в исполняемом файле), а измененные скачиваются в SWAP-файл. Когда данные опять понадобятся, они читаются из разных мест (из исполняемого файла или из SWAP-файла).
В первом случае мы имеем огромный плюс:

  • Нет записи в SWAP-файл (а запись, между прочим, примерно в 3 раза медленнее, чем чтение),
  • Не расходуется виртуальная память.

Теперь про упаковку файла. После проецирования, прежде чем модуль будет готов, он распаковывается специальной подпрограммой. Т.е. сразу при загрузке модуль переписывает всю (!!!) свою память, что заставляет систему выделить ее (память) в отдельный блок. Т.е. ни о какой экономии речь уже не идет. Ладно, если Вы запустили упакованный таким образом NotePad, а если Word? Да еще и 3 раза?

А теперь, непосредственно по теме данной статьи.

Хорошо. Мы вняли голосу умного человека и не стали паковать файл(ы). И казалось бы, все хорошо. НО Ваш проект устроен так, что он использует кучу DLL, которые Вы сами и написали. И у всех у них базовый адрес стоит $10000000(0х10000000-на CPP). А теперь вернемся к загрузке (точнее к пункту 3), попробуем понять что такое базовый адрес и зачем он нужен.
В любой программе есть инструкции, которые привязаны к адресу.

Например:
По адресу $1000000 у нас находится переменная "X";
Где-то мы к ней обращаемся.

...              ; Какой-то код и данные
org 1000000h
X dword ?        ; Переменная Х по адресу $1000000
Y dword ?        ; Переменная Y по адресу $1000004
...              ; Какой-то код и данные
mov eax,[1000000h] ; Обращаемся к переменной
inc eax          ;
mov [1000000h],eax ;
...              ; Какой-то код и данные

А теперь представим ситуацию, что загрузили модуль по другому адресу. Для примера, на 4 байта выше. Получим следующее представление:

...              ; Какой-то код и данные
org 0FFFFFCh
X dword ?        ; Переменная Х по адресу $0FFFFFC
Y dword ?        ; Переменная Y по адресу $1000000
...              ; Какой-то код и данные
mov eax,[1000000h] ; Обращаемся к переменной
inc eax          ;
mov [1000000h],eax ;
...              ; Какой-то код и данные

Смотрим и видим, что программа обращается уже не к переменной X, а к переменной Y. Что совершенно поломает всю логику работы программы. Что делать? Правильно. При загрузке по другому адресу надо аккуратно исправить все такие инструкции. Для этого в модулях есть все данные: Базовый адрес загрузки(Base Address), и таблица перемещений(Relocation Section). После проецирования (шаг 2) система исполняет шаг 3, т.е. если по базовому адресу модуль загрузить не удалось (система всегда сначала пытается загрузить модуль по базовому адресу), то она пытается загрузить его по другому адресу, используя данные о базовом адресе, о действительном адресе и данные из таблицы перемещений(пытается, потому что таблицы перемещений может не быть, тогда говорят, что модуль имеет фиксированный базовый адрес, и загрузить его по другому адресу не возможно). Процесс загрузки по другому адресу долгий. Система пробегает по всему коду, и исправляет адреса на правильные, а таких адресов может быть десятки и сотни тысяч(!!!).

Ну, Вы уже поняли "где собака порылась"? Подсказываю, исправляет код - значит записывает туда другое значение. А теперь понятно? Правильно. Опять вся память модуля летает в SWAP и назад. И системе совершенно все равно, по какой причине произошла запись в код: при распаковке или при исправлении кода. Все равно этот экземпляр уже лежит в памяти "тяжелым грузом".

Причем, как показывает практика, таких DLL(а это относится на 99.9% к ним, т.к. до загрузки EXE в памяти процесса вообще больше ничего нет, и его(EXE) можно грузить куда угодно и по любому адресу), в системе может набираться на мегабайты. У меня например таких DLL набралось на 23М :((((((. Т.е. почти 10% физической памяти(у меня стоит 256M :)))))). Но мне хорошо. Винт быстрый, и 10% это не смертельно. А каково тем, у кого 64М? В конце статьи пример распечатки загруженных DLL для Explorer(Проводника). Жирным выделены модули, загруженные не по базовым адресам. Общая длина модулей ~1.8 метра.:(((((((

Причем самое странное, что не только рядовые программеры не заботятся об этой проблеме (извините, народ, но мы почти все, и я в том числе, относимся к рядовым) но и "бренды" вроде Касперского, Intel, и др. делают то же самое.

Как исправить создавшееся положение? К сожалению, готового решения данной проблемы у меня нет. С Visual Studio идет программа ReBase.exe, которая изменяет базовый адрес указанного модуля. Но это надо сидеть и аккуратно все(!!!) DLL исправлять. А их у меня в системе, более 5 тысяч. Поэтому этот вопрос был, есть, и "будет есть". А эта статья призвана убедить Вас уменьшить обьем хаоса в этом мире. Конечно, разные разработчики вполне могут загнать свои DLL по одному и тому же адресу. Поэтому я, для себя, например, выбрал такую тактику, все свои DLL я гружу, начиная с адреса $20000000, причем ни одна DLL не пересекается с другой, даже из разных проектов. Для этого, правда, приходиться иметь базу данных уже использованных адресов. Как показывает практика и анализ процессов в системе, системные DLL Windows имеют разный базовый адрес. Более того, некоторые из них имеют фиксированный базовый адрес(см. Пример). А также, можно заметить, что с адреса $20000000 и до адреса $30000000 с копейками, пустое пространство. Вот это место я себе и облюбовал :)))).

Вывод. В системе всегда есть "плохие" модули. Но если Вы свои модули будете разносить по разным адресам, то и стандартные модули будут грузиться по базовым адресам, и в конечном итоге Ваша система будет работать быстрее и эфективнее.

Михаил Басов


Process: Explorer.exe. Modules Information.

Usage	Image Addr	Base Addr	Size	Module
1	00B10000	10000000	32768	F:\PROGRA~1\Adobe\ACROBA~1\Reader\ActiveX\AcroIEHelper.ocx
1	00F00000	10000000	24576	F:\PROGRA~1\Logitech\MOUSEW~1\SYSTEM\LGMOUSHK.dll
Fixed	01000000		        1011712	F:\WINDOWS\Explorer.EXE
2	01750000	10000000	552960	F:\WINDOWS\System32\NOVNPNT.DLL
2	017E0000	10000000	221184	F:\WINDOWS\System32\MAPBASE.dll
1	018E0000	6A400000	65536	F:\WINDOWS\System32\NLS\ENGLISH\NWSHLXNR.DLL
2	01A20000	10000000	184320	F:\WINDOWS\System32\NWSHLXNT.dll
1	01D10000	6A400000	225280	F:\WINDOWS\System32\NLS\ENGLISH\NOVNPNTR.DLL
1	01ED0000	10000000	114688	F:\PROGRA~1\Common Files\Adobe\Shell\PSICON.DLL
1	02210000	10000000	53248	F:\PROGRA~1\KASPER~1\ANTIVI~1\avpshlex.dll
1	02230000	01500000	147456	F:\Program Files\WinRAR\rarext.dll
1	02A70000	10000000	217088	F:\Program Files\7-ZIP\7-zipn.dll
1	0FFD0000	        	139264	F:\WINDOWS\System32\rsaenh.dll
1	10000000	        	16384	F:\Program Files\Punto Switcher\correct.dll
4	1F7B0000	        	200704	F:\WINDOWS\System32\ODBC32.dll
1	1F850000	        	90112	F:\WINDOWS\System32\odbcint.dll
1	32270000	        	28672	F:\Program Files\Miranda\Plugins\BOSSKEY.DLL
1	32520000			73728	F:\Program Files\Microsoft Office\Office10\msohev.dll
8	50D00000	        	86016	F:\WINDOWS\System32\CLNWIN32.DLL
6	50D20000	        	163840	F:\WINDOWS\System32\CALWIN32.DLL
6	50D50000	        	282624	F:\WINDOWS\System32\NETWIN32.DLL
6	50DA0000	        	45056	F:\WINDOWS\System32\CLXWIN32.DLL
6	50DB0000	        	167936	F:\WINDOWS\System32\NCPWIN32.dll
16	50DF0000	        	131072	F:\WINDOWS\System32\LOCWIN32.DLL
Fixed	5AD70000	        	212992	F:\WINDOWS\System32\UxTheme.dll
1	5B630000	        	458752	F:\WINDOWS\System32\themeui.dll
1	68880000		        258048	F:\WINDOWS\System32\hnetcfg.dll
1	6A400000		        110592	F:\WINDOWS\System32\NLS\ENGLISH\MAPBASER.DLL
2	6C1B0000		        274432	F:\WINDOWS\System32\DUSER.dll
16	71AA0000		        32768	F:\WINDOWS\system32\WS2HELP.dll
26	71AB0000		        86016	F:\WINDOWS\system32\WS2_32.dll
2	71AD0000		        32768	F:\WINDOWS\System32\WSOCK32.dll
12	71B20000		        69632	F:\WINDOWS\system32\MPR.dll
4	71BF0000		        69632	F:\WINDOWS\System32\SAMLIB.dll
1	71C10000		        53248	F:\WINDOWS\System32\ntlanman.dll
31	71C20000		        323584	F:\WINDOWS\System32\NETAPI32.dll
2	71C80000		        24576	F:\WINDOWS\System32\NETRAP.dll
1	71C90000		        245760	F:\WINDOWS\System32\NETUI1.dll
2	71CD0000		        90112	F:\WINDOWS\System32\NETUI0.dll
1	71D40000		        110592	F:\WINDOWS\System32\ACTXPRXY.DLL
2	72410000		        102400	F:\WINDOWS\System32\mydocs.dll
1	72430000		        73728	F:\WINDOWS\System32\browselc.dll
2	72D10000		        32768	F:\WINDOWS\System32\msacm32.drv
4	72D20000		        36864	F:\WINDOWS\System32\wdmaud.drv
2	73000000		        143360	F:\WINDOWS\System32\WINSPOOL.DRV
1	73380000		        331776	F:\WINDOWS\System32\zipfldr.dll
1	74770000	        	585728	F:\WINDOWS\System32\MLANG.dll
2	74AD0000	        	28672	F:\WINDOWS\System32\POWRPROF.dll
1	74AE0000	        	28672	F:\WINDOWS\System32\CFGMGR32.dll
1	74AF0000	        	36864	F:\WINDOWS\System32\BatMeter.dll
1	74B00000	        	131072	F:\WINDOWS\System32\stobject.dll
1	74B30000	        	266240	F:\WINDOWS\System32\webcheck.dll
1	74B80000	        	532480	F:\WINDOWS\System32\printui.dll
1	74ED0000	        	61440	F:\WINDOWS\System32\wbem\wbemsvc.dll
1	74EF0000	        	40960	F:\WINDOWS\System32\wbem\wbemprox.dll
1	74FC0000	        	65536	F:\WINDOWS\System32\CLUSAPI.dll
2	75290000	        	229376	F:\WINDOWS\System32\wbem\wbemcomn.dll
1	755F0000	        	593920	F:\WINDOWS\System32\netcfgx.dll
1	75690000	        	598016	F:\WINDOWS\System32\wbem\fastprox.dll
4	75970000	        	987136	F:\WINDOWS\System32\MSGINA.dll
10	75A70000		    	667648	F:\WINDOWS\system32\USERENV.dll
2	75CF0000	        	1638400	F:\WINDOWS\system32\NETSHELL.dll
1	75E90000	        	659456	F:\WINDOWS\System32\SXS.DLL
2	75F40000	        	118784	F:\WINDOWS\system32\appHelp.dll
1	75F60000	        	24576	F:\WINDOWS\System32\drprov.dll
1	75F70000	        	36864	F:\WINDOWS\System32\davclnt.dll
Fixed	75F80000	        	1032192	F:\WINDOWS\System32\BROWSEUI.dll
1	760F0000	        	491520	F:\WINDOWS\System32\urlmon.dll
1	76170000	        	557056	F:\WINDOWS\System32\shdoclc.dll
2	76200000	        	618496	F:\WINDOWS\system32\WININET.dll
5	762A0000	        	61440	F:\WINDOWS\system32\MSASN1.dll
5	762C0000	        	565248	F:\WINDOWS\system32\CRYPT32.dll
11	76360000	        	61440	F:\WINDOWS\System32\WINSTA.dll
2	76380000	        	20480	F:\WINDOWS\System32\MSIMG32.dll
5	763B0000	        	282624	F:\WINDOWS\system32\comdlg32.dll
2	76400000	        	2076672	F:\WINDOWS\System32\msi.dll
5	76600000	        	110592	F:\WINDOWS\System32\CSCDLL.dll
3	76620000	        	319488	F:\WINDOWS\System32\cscui.dll
7	76670000                	933888	F:\WINDOWS\System32\SETUPAPI.dll
1	76980000	        	28672	F:\WINDOWS\System32\LINKINFO.dll
5	76990000	        	147456	F:\WINDOWS\System32\ntshrui.dll
Fixed	769C0000			1347584	F:\WINDOWS\System32\SHDOCVW.dll
8	76B20000		        86016	F:\WINDOWS\System32\ATL.DLL
17	76B40000		        180224	F:\WINDOWS\System32\WINMM.dll
2	76C00000		        184320	F:\WINDOWS\system32\credui.dll
1	76C30000		        176128	F:\WINDOWS\System32\WINTRUST.dll
1	76C90000		        139264	F:\WINDOWS\system32\IMAGEHLP.dll
2	76D30000		        16384	F:\WINDOWS\system32\WMI.dll
2	76D40000		        90112	F:\WINDOWS\system32\MPRAPI.dll
7	76D60000		        86016	F:\WINDOWS\system32\iphlpapi.dll
3	76D80000		        106496	F:\WINDOWS\system32\DHCPCSVC.DLL
2	76DA0000		        196608	F:\WINDOWS\system32\WZCSvc.DLL
2	76DE0000		        155648	F:\WINDOWS\system32\netman.dll
4	76E10000		        147456	F:\WINDOWS\system32\adsldpc.dll
3	76E40000		        192512	F:\WINDOWS\system32\ACTIVEDS.dll
9	76E80000		        53248	F:\WINDOWS\system32\rtutils.dll
4	76E90000		        69632	F:\WINDOWS\system32\rasman.dll
4	76EB0000		        172032	F:\WINDOWS\system32\TAPI32.dll
5	76EE0000		        225280	F:\WINDOWS\system32\RASAPI32.dll
3	76F20000		        151552	F:\WINDOWS\system32\DNSAPI.dll
3	76F50000		        32768	F:\WINDOWS\System32\WTSAPI32.dll
3	76F60000		        180224	F:\WINDOWS\system32\WLDAP32.dll
9	76F90000		        65536	F:\WINDOWS\System32\Secur32.dll
2	76FD0000		        491520	F:\WINDOWS\System32\CLBCATQ.DLL
2	77050000		        806912	F:\WINDOWS\System32\COMRes.dll
Fixed	77120000		        569344	F:\WINDOWS\system32\OLEAUT32.dll
Fixed	771B0000		        1155072	F:\WINDOWS\system32\ole32.dll
Fixed	772D0000		        405504	F:\WINDOWS\system32\SHLWAPI.dll
14	77340000		        569344	F:\WINDOWS\system32\comctl32.dll
Fixed	773D0000		        8339456	F:\WINDOWS\system32\SHELL32.dll
1	77BD0000		        28672	F:\WINDOWS\System32\midimap.dll
2	77BE0000		        81920	F:\WINDOWS\System32\MSACM32.dll
10	77C00000		        28672	F:\WINDOWS\system32\VERSION.dll
Fixed	77C10000		        339968	F:\WINDOWS\system32\msvcrt.dll
Fixed	77C70000		        262144	F:\WINDOWS\system32\GDI32.dll
Fixed	77CC0000		        479232	F:\WINDOWS\system32\RPCRT4.dll
Fixed	77D40000		        577536	F:\WINDOWS\system32\USER32.dll
Fixed	77DD0000		        569344	F:\WINDOWS\system32\ADVAPI32.dll
Fixed	77E60000		        937984	F:\WINDOWS\system32\kernel32.dll
Fixed	77F50000		        692224	F:\WINDOWS\System32\ntdll.dll

Примечание:
  • 1-я колонка: Fixed-Нет таблицы перемещения, 1,2,3..-сколько раз модуль был загружен
  • 2-я колонка: Адрес по которому загружен модуль
  • 3-я колонка: Базовый адрес модуля(если пуст, то модуль загружен по базовому адресу)
  • 4-я колонка: Размер модуля в байтах
  • 5-я колонка: Полный путь к модулю




К материалу прилагаются файлы:


Смотрите также материалы по темам:
[Использование и создание DLL] [Параметры процесса/приложения]

 Обсуждение материала [ 17-07-2008 11:56 ] 17 сообщений
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования