2

在具有 gcc 的 Linux 主机下构建时,我在 EDK2(x64 shell 应用程序)下使用变量参数时遇到问题。程序构建但在执行时会在执行 VA_ARG() 时导致页面错误。

在带有 VS2015 的 Windows 主机下构建的相同代码可以正常工作。

这似乎与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;
}
4

1 回答 1

3

我找到了一个修复方法,那就是用EFIAPI标签定义函数,这解决了这个问题,即

VOID EFIAPI PrintInts(UINTN n, ...)

从这个链接:

创建 32 位 UEFI 应用程序时,EFIAPI 为空;GCC 将使用标准 C 调用约定编译“efi_main”函数。创建 64 位 UEFI 应用程序时,EFIAPI 扩展为“__attribute__((ms_abi))”,GCC 将使用 UEFI 指定的 Microsoft 的 x64 调用约定编译“efi_main”函数。只有将从 UEFI 直接调用的函数(包括主函数,也包括回调函数)需要使用 UEFI 调用约定。

此外,它似乎只是 GCC 的一个问题,好像我使用 CLANG 我不需要指定 EFIAPI。

于 2021-11-03T10:25:33.360 回答