2

I am having issues with using variable arguments under EDK2 (x64 shell application) when built under a Linux host with gcc. Program builds but when executed it will cause a page fault at the point VA_ARG() is executed.

The same code when built under a Windows host with VS2015 works without issue.

This seems related to GCC bug 50818 but I can find no solution.

#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 Answers1

3

I have found a fix and that is to define the function with the EFIAPI tag and this fixes the issue, i.e.

VOID EFIAPI PrintInts(UINTN n, ...)

From this link:

When creating a 32-bit UEFI application, EFIAPI is empty; GCC will compile the "efi_main" function using the standard C calling convention. When creating a 64-bit UEFI application, EFIAPI expands to "__attribute__((ms_abi))" and GCC will compile the "efi_main" function using Microsoft's x64 calling convention, as specified by UEFI. Only functions that will be called directly from UEFI (including main, but also callbacks) need to use the UEFI calling convention.

Also it only seem to be an issue with GCC as if I use CLANG I do not need to specify EFIAPI.