#c #gcc #clang #uefi #edk2
Вопрос:
У меня возникли проблемы с использованием переменных аргументов в EDK2 (приложение оболочки x64) при сборке под хостом Linux с gcc. Программа строится, но при выполнении она вызовет ошибку страницы в момент выполнения функции VA_ARG ().
Тот же код, созданный под хостом Windows с VS2015, работает без проблем.
Это, похоже, связано с ошибкой GCC 50818, но я не могу найти решения.
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/PrintLib.h>
#include <Library/ShellCEntryLib.h>
VOID PrintInts(UINTN n, ...)
{
VA_LIST vl;
VA_START(vl, n);
Print(L"Printing integers:");
for (UINTN i=0; i<n; i ) {
UINTN val = 0;
val = VA_ARG(vl, UINTN);
Print(L" [%d]", val);
}
VA_END(vl);
Print(L"n");
}
INTN EFIAPI ShellAppMain(IN UINTN Argc, IN CHAR16 **Argv)
{
UINTN a = 3;
UINTN b = 10;
UINTN c = 9;
PrintInts(3, a, b, c);
return 0;
}
Ответ №1:
Я нашел исправление, которое заключается в определении функции с EFIAPI
помощью тега, и это устраняет проблему, т. Е.
VOID EFIAPI PrintInts(UINTN n, ...)
При создании 32-разрядного приложения UEFI EFIAPI пуст; GCC скомпилирует функцию «efi_main», используя стандартное соглашение о вызовах C. При создании 64-разрядного приложения UEFI EFIAPI расширяется до «__атрибут__((ms_abi))», и GCC скомпилирует функцию «efi_main», используя соглашение о вызовах x64 корпорации Майкрософт, как указано в UEFI. Только функции, которые будут вызываться непосредственно из UEFI (включая основные, но также обратные вызовы), должны использовать соглашение о вызовах UEFI.
Кроме того, это только кажется проблемой с GCC, как если бы я использовал CLANG, мне не нужно указывать EFIAPI.