#c #linker #static-linking
#c #компоновщик #статическое связывание
Вопрос:
Я скомпилировал программу на C и связался с компоновщиком Microsoftlink.exe. Компоновщик сгенерировал файл *.map. Ниже приведены некоторые фрагменты:
Start Length Name Class
0001:00000000 00000180H .text CODE
0001:00000180 00049158H .text$mn CODE
0002:00000000 000090c4H .rdata DATA
0002:000090c4 00000130H .rdata$zzzdbg DATA
0003:00000000 00002060H .data DATA
0003:00002060 00001370H .bss DATA
0004:00000000 00002790H .pdata DATA
0005:00000000 000003e4H .xdata DATA
Address Publics by Value Rva Base Lib:Object
0002:000000c0 _gVar 0000000000049660 MyLib:File1.obj
Насколько я понимаю,:
.rdata
Раздел имеет индекс 0002
с указанием длины 0x90c4
.
_gVar
Глобальная переменная имеет адрес like 0002:000000c0
, поэтому она находится в .rdata
разделе со смещением раздела. ………. 0xc0
Базовый адрес .rdata
раздела определяется загрузчиком во время выполнения.
Мое замешательство связано с Rva Base
колонкой.
Я проверил двоичный файл со смещением 0x49660
. Он содержит именно то значение, которое я присвоил для _gVar
. Похоже, что это Rva Base
это смещение от начала файла.
Но я думаю, что Rva Base
должно быть равно absolute virtual address
, что может быть определено только загрузчиком во время выполнения.
Как это может быть смещение файла? Или неудачная опечатка в имени столбца?
(Кстати, я много искал авторитетную ссылку на файл .map, созданный link.exe . Но пока безуспешно. Если кто-нибудь может поделиться каким-либо ресурсом, это будет высоко оценено.)
ДОБАВИТЬ 1 — 5:31 ВЕЧЕРА, 4/8/2019
Основываясь на 500 - Internal Server Error
комментарии, я использую CFF Explorer для проверки разделов PE. Это выглядит следующим образом:
Согласно PE sepc:
Виртуальный адрес: для исполняемых изображений — адрес первого байта раздела относительно базы изображений, когда раздел загружен в память.
Необработанный адрес/PointerToRawData: указатель файла на первую страницу раздела в файле COFF.
Эти 2 столбца имеют одинаковые данные в моем сценарии.
А в необязательном заголовке PE база изображений равна 0 (это из-за моего флага ссылки /BASE:0
):
Когда компоновщик сгенерировал файл .map, он не имеет представления о том, где изображение будет загружено во время выполнения. Поэтому он должен использовать ImageBase=0
для вычисления Rva Base
столбца.
_gVar
Абсолютный виртуальный адрес = база изображений (0) виртуальный адрес .rdata (0x495A0) смещение в .rdata (0xc0) = 0x49660
В моем случае,
Virtual Address
Столбец имеет то же значение, что иRaw Address
столбец.- И
ImageBase = 0
имеет тот же эффектfile beginning offset = 0
Таким образом, конечное значение absolute virtual address
равно file offset
, но это относится только к моему сценарию.
Комментарии:
1. Проанализируйте заголовок PE. У него есть таблица с расположением каждого раздела, как в виде смещения в файл на диске, так и в виде смещения к адресу загрузки модуля в памяти, когда PE загружается как исполняемый файл или dll. Вот ссылка на спецификацию PE.