打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
CONFIG

问题现象

最近在交叉编译 X86-64 平台的 Linux 内核时,出现如下编译警告:

CONFIG_X86_X32 enabled but no binutils support

查看 .config 文件确实打开了 CONFIG_X86_X32:

CONFIG_X86_X32=y

arch/x86/Kconfig 中找到对 CONFIG_X86_X32 的说明:

config X86_X32
    bool "x32 ABI for 64-bit mode"
    depends on X86_64
    ---help---
      Include code to run binaries for the x32 native 32-bit ABI      for 64-bit processors.  An x32 process gets access to the
      full 64-bit register file and wide data path while leaving
      pointers at 32 bits for smaller memory footprint.

      You will need a recent binutils (2.22 or later) with
      elf32_x86_64 support enabled to compile a kernel with this
      option set.

由上述说明可知,CONFIG_X86_X32 选项用于在 64 位处理器上运行原生 32 位程序,需要 binutils 2.22 或更高版本(带 elf32_x86_64 支持)。

源码分析

在内核源码中搜索上述警告,定位到 arch/x86/Makefile

ifdef CONFIG_X86_X32
    x32_ld_ok := $(call try-run,            /bin/echo -e '1: .quad 1b' | \            $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" - && \            $(OBJCOPY) -O elf32-x86-64 "$$TMP" "$$TMPO" && \            $(LD) -m elf32_x86_64 "$$TMPO" -o "$$TMP",y,n)
        ifeq ($(x32_ld_ok),y)
                CONFIG_X86_X32_ABI := y
                KBUILD_AFLAGS += -DCONFIG_X86_X32_ABI
                KBUILD_CFLAGS += -DCONFIG_X86_X32_ABI        else
                $(warning CONFIG_X86_X32 enabled but no binutils support)
        endifendif

此段代码即是根据 try-run 的运行结果确定工具链是否支持 elf32_x86_64,如果支持则定义 CONFIG_X86_X32_ABI,否则输出前述编译警告。

try-runscripts/Kbuild.include 中定义:

# output directory for tests belowTMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)# try-run# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)# Exit code chooses option. "$$TMP" serves as a temporary file and is# automatically cleaned up.try-run = $(shell set -e;           TMP="$(TMPOUT).$$$$.tmp";       TMPO="$(TMPOUT).$$$$.o";    \    if ($(1)) >/dev/null 2>&1;      then echo "$(2)";       \    else echo "$(3)";           fi;                 rm -f "$$TMP" "$$TMPO")

其作用是执行第一个入参指定的命令,如果成功则输出第二个入参,失败则输出第三个入参,最后删除临时目录下的两个临时文件。

结合 arch/x86/Makefile 的使用情况,完成如下三个操作:

  • 将一行汇编语句使用 gcc 编译成 .$$$$.tmp

  • 使用 objcopy.$$$$.tmp 转换为 elf32-x86-64 格式的 .$$$$.o

  • 最后使用 ld.$$$$.o 链接为 elf32_x86_64 目标的 .$$$$.tmp(复用此文件名)。

假如三个操作都没有错误发生,表明目标工具链支持 x32 ABI 对应的选项,则 x32_ld_ok 变量赋值为 y,否则赋值为 n

其中要编译的汇编语句仅有一行,作用是定义一个值为 1 的 64 比特数值,仅用于后续的选项测试,没有实际功能:

1: .quad 1b

查看工具链支持的编译目标

objcopy --help 的最后可查看其支持的目标,其中包括 elf32-86-64,各个目标可作为 -O 参数传入:

objcopy: supported targets: elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big pe-x86-64 pe-bigobj-x86-64 pe-i386 plugin srec symbolsrec verilog tekhex binary ihex

ld -V 可查看其支持的目标,其中包括 elf32_86_64,各个目标可作为 -m 参数传入:

# ld -VGNU ld (GNU Binutils for Ubuntu) 2.31.1
  Supported emulations:
   elf_x86_64
   elf32_x86_64
   elf_i386
   elf_iamcu
   elf_l1om
   elf_k1om
   i386pep
   i386pe

注意:objcopyld 参数值的不同(elf32-86-64elf32_86_64)。

解决方法

假如查看到的工具链不支持需要的目标,只需升级工具链再重新编译内核即可。

小结

  • 64 位处理器运行原生 32 位程序,需要打开内核 CONFIG_X86_X32 选项。

  • CONFIG_X86_X32 选项需要工具链支持编译 elf32_x86_64 目标。

  • objcopy --helpld -V 可查看两个命令支持的目标格式。

以上。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
GNU Binutils详解
ARM linux解析之zImage镜像文件的生成
编写简单的Makefile文件
Linux内核构建系统之八
STM32高级开发(7)
linux
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服