使用 GCC 构建的变量参数的 EDK2 Shell 应用程序在运行时会导致页面错误

Posted

技术标签:

【中文标题】使用 GCC 构建的变量参数的 EDK2 Shell 应用程序在运行时会导致页面错误【英文标题】:EDK2 Shell Application using Variable Arguments built with GCC causes Page Fault when run 【发布时间】:2021-12-17 04:11:23 【问题描述】:

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

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

这似乎与GCC bug 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, ...)

From this link:

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

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

【讨论】:

以上是关于使用 GCC 构建的变量参数的 EDK2 Shell 应用程序在运行时会导致页面错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Qt Creator 中启用自定义 gcc 参数? [复制]

如何在 GCC 的 32 字节边界处对齐堆栈?

使用变量包含参数在生成文件中添加 Windows 包含路径

GCC强制静态库链接未使用的函数变量

gcc 警告“在 GCC 7.1 中为 X 传递的项目参数已更改”是啥意思?

GCC 可以使用编译时常量变量优化类的方法吗?