пятница, 15 октября 2021 г.

Что означает поле SizeOfImage в структуре MODULEINFO?

Это перевод What does the SizeOfImage mean in the MODULEINFO structure? Автор: Реймонд Чен.

У одного клиента была программа с поддержкой плагинов, и клиент хотел провести анализ занимаемой плагинами памяти. Клиент уже умел отслеживать выделение динамической памяти плагинами (поскольку его модель плагинов была очень ограниченной), но его интересовал объём памяти, занимаемый кодом модуля и сегментами статических данных. Клиент получал информацию о плагине, вызывая функцию GetModuleInformation и просматривая поле SizeOfImage, но ему нужна была помощь в интерпретации этого значения. Будет ли SizeOfImage учитывать, например, большой статический массив с инициализацией нулями? Клиент знал, что обнулённые статические данные обычно не занимают места в самом файле, но добавляются ли они в SizeOfImage? И вообще, SizeOfImage - это размер чего именно?

Вспомните, что структура MODULEINFO формируется загрузчиком ОС, а задача загрузчика - управлять модулями, загруженными процессом. SizeOfImage в паре с lpBaseOfDll описывают диапазон виртуальных адресов, который занимает образ модуля (DLL) после загрузки с диска. Загрузчик использует эту информацию для различных целей - в том числе для ответа на флаг GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, передаваемый в функцию GetModuleHandleEx.

Размер модуля в виртуальном адресном пространстве включает в себя его код, статические данные и ресурсы. В целом, он может быть как больше, так и меньше размера файла: файл на диске может содержать байты, которые вообще не отображаются в адресное пространство - например, сертификат цифровой подписи или любую дополнительную полезную нагрузку, добавленную в конец файла. С другой стороны, в виртуальном адресном пространстве есть вещи, которых нет в файле - например, данные с нулевой инициализацией или межсекционное заполнение (padding). Модуль вообще может даже намеренно разметить свое адресное пространство с промежутками между разделами, превышающими минимум, необходимый для поддержания выравнивания.

Если вы хотите измерить объём памяти, занимаемый плагином, вам необходимо принять все эти моменты во внимание. Хотите ли вы подсчитывать данные для чтения/записи отдельно от кода, ресурсов и других данных только для чтения? Не всякий код, ресурсы и данные из виртуального адресного пространства будут в файле.

Решение о том, какие разделы считать, а какие нет - это вопрос, на который можете ответить только вы. В этом вам может помочь сам модуль, в заголовке которого будут поля SizeOfCode, SizeOfData и SizeOfUninitializedData, что избавит вас от необходимости вычислять эти значения самостоятельно. Они охватывают код, данные (любые: и для чтения и для чтения/записи) и данные с нулевой инициализацией соответственно. Эти значения могут стать отправной точкой, если вас не интересуют таблица перемещений (relocation table), ресурсы или таблицы исключений.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.

Примечание. Отправлять комментарии могут только участники этого блога.