Step to UEFI (123)NOOPT 编译问题

之前我们在介绍 Source Level Debug 的文章中使用过 Noopt 的选项。后来找人请教了一下这个编译目标的含义:关闭一切编译优化。我猜测这样做的目的是为了让编译结果很容易实现汇编和 Source Code的一一对应。但是,很多情况下,编写EDK2代码的人都会忘记测试这个选项,于是,直接下载的代码会碰到X64 IA32 一切正常,唯独=在这个编译目标上发生问题。
比如,最近我又碰到了关于这个编译目标的问题,下面是简化之后的代码,可以帮助展示这个问题:

#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiApplicationEntryPoint.h>

/**
  The user Entry Point for Application. The user code starts with this function
  as the real entry point for the application.

  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  
  @param[in] SystemTable    A pointer to the EFI System Table.
  
  @retval EFI_SUCCESS       The entry point is executed successfully.
  @retval other             Some error occurs when executing this entry point.

**/
EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
        UINTN  *z;
        UINT64 x;
  z=(UINTN  *)1024;  //取内存 1024处的值,这里只是为了演示没有实际意义
                                     //如果直接赋值常数,在编译过程中会被优化掉
  x=*z;

  Print (L"%d",x / 1024);
  return EFI_SUCCESS;
}

 

上面的代码在下面的编译命令时

Build –a IA32 –p MdeModulePkg/MdeModulePkg.dsc –b NOOPT 

 

会出现这样的报错

"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\link.exe" /OUT:c:\buildbs\test\Build\MdeModule\NOOPT_VS2015x86\IA32\MdeModulePkg\Application\NooptTest\NooptTest\DEBUG\NooptTest.dll /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:_ModuleEntryPoint /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG @c:\buildbs\test\Build\MdeModule\NOOPT_VS2015x86\IA32\MdeModulePkg\Application\NooptTest\NooptTest\OUTPUT\static_library_files.lst
NooptTest.lib(NooptTest.obj) : error LNK2001: unresolved external symbol __aulldiv
c:\buildbs\test\Build\MdeModule\NOOPT_VS2015x86\IA32\MdeModulePkg\Application\NooptTest\NooptTest\DEBUG\NooptTest.dll : fatal error LNK1120: 1 unresolved externals
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\link.exe"' : return code '0x460'
Stop.

build...
: error 7000: Failed to execute command
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\nmake.exe /nologo tbuild [c:\buildbs\test\Build\MdeModule\NOOPT_VS2015x86\IA32\MdeModulePkg\Application\NooptTest\NooptTest]

具体原因我不清楚,-b Release 以及 –b Debug 都不存在问题,可以确定和 NOOPT 模式有关。
标准的解决方法是使用 BaseLib.h 中的DivU64x32函数来代替直接除法运算避免这个问题。同样的,如果针对64位变量进行左移右移也会遇到类似的问题,同样在
BaseLib.h 中可以找到替代的函数。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注