В данной статье мы рассмотрим вопрос о записи данных в исполняемые файлы (ELF и PE/COFF) в контексте программирования на Object Pascal (Delphi). Мы изучим, как данные записываются в эти форматы, и как это может повлиять на поведение приложения на разных платформах.
Введение
ELF (Executable and Linkable Format) и PE/COFF (Portable Executable/Common Object File Format) — это форматы исполняемых файлов, используемые в Linux и Windows соответственно. При написании кода на Object Pascal (Delphi) разработчики могут столкнуться с различиями в поведении данных при записи в эти форматы. В данной статье мы рассмотрим, как запись данных в ELF и PE/COFF может отличаться, и как это может повлиять на приложение.
Запись данных в ELF
При записи данных в ELF, данные помещаются в секцию .rodata (читаемые-only данные) или .data (инициализируемые данные). Пример записи данных в ELF показан в следующем фрагменте кода на Object Pascal (Delphi):
program WriteDataToELF;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
TEFI-SystemTable = record
hdr: TEFI-TableHeader;
FirmWareVendor: PAnsiChar;
FirmWareRevision: Cardinal;
ConsoleInHandle: TEFI-Handle;
ConIn: PTEFI-SimpleTextInputProtocol;
ConsoleOutHandle: TEFI-Handle;
ConOut: PTEFI-SimpleTextOutputProtocol;
StandardErrorHandle: TEFI-Handle;
StdErr: PTEFI-SimpleTextOutputProtocol;
RuntimeServices: PTEFI-RuntimeServices;
BootServices: PTEFI-BootServices;
NumberOfTableEntries: NativeUint;
ConfigurationTable: PTEFI-ConfigurationTable;
end;
var
EFI-SystemTable: TEFI-SystemTable;
begin
EFI-SystemTable.FirmWareVendor := 'FreePascal';
EFI-SystemTable.FirmWareRevision := $00000001;
// Другие поля также инициализируются здесь
end.
При компиляции этого кода с помощью Free Pascal (fpc) и опцией -n (без генерации кода на ассемблере) мы получим исполняемый файл в формате ELF. При просмотре этого файла с помощью утилиты objdump мы увидим, что данные помещены в секцию .data:
При записи данных в PE/COFF, данные помещаются в секцию .data или .rdata (только для чтения). Пример записи данных в PE/COFF показан в следующем фрагменте кода на Object Pascal (Delphi):
program WriteDataToPECOFF;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
TEFI-SystemTable = record
hdr: TEFI-TableHeader;
FirmWareVendor: PAnsiChar;
FirmWareRevision: Cardinal;
ConsoleInHandle: TEFI-Handle;
ConIn: PTEFI-SimpleTextInputProtocol;
ConsoleOutHandle: TEFI-Handle;
ConOut: PTEFI-SimpleTextOutputProtocol;
StandardErrorHandle: TEFI-Handle;
StdErr: PTEFI-SimpleTextOutputProtocol;
RuntimeServices: PTEFI-RuntimeServices;
BootServices: PTEFI-BootServices;
NumberOfTableEntries: NativeUint;
ConfigurationTable: PTEFI-ConfigurationTable;
end;
var
EFI-SystemTable: TEFI-SystemTable;
begin
EFI-SystemTable.FirmWareVendor := 'FreePascal';
EFI-SystemTable.FirmWareRevision := $00000001;
// Другие поля также инициализируются здесь
end.
При компиляции этого кода с помощью Free Pascal (fpc) и опцией -Xd (для целевой платформы Windows) мы получим исполняемый файл в формате PE/COFF. При просмотре этого файла с помощью утилиты dumpbin мы увидим, что данные помещены в секцию .data:
Microsoft (R) COFF/PE Dumper Version 14.20.27508.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file WriteDataToPECOFF.exe
File Type: EXECUTABLE IMAGE
Section #1
.data size 100
No Pad
Различия в поведении данных
Из приведенных примеров видно, что при записи данных в ELF и PE/COFF данные помещаются в разные секции: в ELF данные помещаются в секцию .data, а в PE/COFF — в секцию .data или .rdata. Это может привести к различиям в поведении данных на разных платформах.
Например, в вопросе, на который дана ссылка в начале статьи, пользователь обнаружил различия в поведении данных при чтении и записи в ELF и PE/COFF. При просмотре сгенерированного ассемблерного кода он заметил, что инструкции movq различаются в зависимости от целевой платформы. Это связано с тем, что в ELF используется относительный адрес (movq U_$UEFI_$$_GLOBALSYSTEMTABLE@GOTPCREL(%rip),%rax), а в PE/COFF — абсолютный адрес (movq U_$UEFI_$$_GLOBALSYSTEMTABLE(%rip),%rax).
Заключение
В данной статье мы рассмотрели вопрос о записи данных в исполняемые файлы (ELF и PE/COFF) в контексте программирования на Object Pascal (Delphi). Мы изучили, как данные записываются в эти форматы, и как это может повлиять на поведение приложения на разных платформах. При записи данных в ELF и PE/COFF данные помещаются в разные секции, что может приводить к различиям в поведении данных на разных платформах. Разработчикам следует учитывать эти различия при написании кода и тестировании приложений на разных платформах.
Альтернативное решение
В качестве альтернативного решения можно использовать целевые платформы, которые обеспечивают единообразное поведение данных при записи в ELF и PE/COFF. Например, можно использовать целевую платформу "UEFI" в Free Pascal, которая обеспечивает единообразное поведение данных на разных платформах. Это позволяет разработчикам писать код, не беспокоясь о различиях в поведении данных на разных платформах.
В данной статье рассматривается вопрос о записи данных в исполняемые файлы (ELF и PE/COFF) в контексте программирования на Object Pascal (Delphi), изучаются различия в поведении данных при записи в эти форматы и их влияние на приложение на разных платформ
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS