WSL64 运行 32 位程序

WSL1 下执行 x86 程序较为困难,需要进行较多步骤,并且存在局限性;

WSL2 下可以直接执行 x86 程序,但需要从 WSL1 中升级上去。

两种操作均较为麻烦,因此这里记录了一点笔者走过的弯路。

1. WSL1

  • 直接复制以下指令至 wsl 中,执行完成之后 gcc / g++ 就可以成功编译 32 位程序并运行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # 启动32位支持层
    sudo dpkg --add-architecture i386
    sudo apt-get update

    # 安装 qemu
    sudo apt install qemu-user-static

    # 配置 x86 elf 在 qemu 中运行
    sudo update-binfmts --install i386 /usr/bin/qemu-i386-static --magic '\x7fELF\x01\x01\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x00\x01\x00\x00\x00' --mask '\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xff\xff\xff\xff\xff\xff\xff'

    # 启动服务
    sudo service binfmt-support start

    # 将启动服务命令别名 32 写入 .zshrc,并重新加载配置文件
    echo "alias 32='sudo service binfmt-support start'" >> ~/.zshrc
    source ~/.zshrc

    # 安装一些基本x86库
    sudo apt-get install g++-multilib libc6:i386 libgcc1:i386 gcc-9-base:i386 libstdc++6:i386
    sudo apt autoremove
  • 但是,即便可以编译并运行32位程序,但仍然无法被 gdb 调试,即 64位的 gdb 无法调试 32 位的程序。

    报错提示所选体系结构 i386 与报告的目标体系结构 i386:x86-64 不兼容:

    1
    2
    warning: Selected architecture i386 is not compatible with reported target architecture i386:x86-64
    warning: Architecture rejected target-supplied description

    此时就必须折中,使用以下这种方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 在 qemu 中启动调试,端口号为 1234
    qemu-i386-static -g 1234 <process>

    # 新开一个终端,启动gdb
    gdb
    # 在 gdb 中设置架构为 i386(不设置貌似也没事?)
    pwndbg> set architecture i386
    # 连接至本地 1234 的 qemu 端口
    pwndbg> target remote 127.0.0.1:1234
    # 试图加载符号
    pwndbg> file <process>

    不过这种方法有局限性,没办法将符号加载出来。

    再一种更硬核的方式就是下载 gdb 源码并编译,不过暂且还没试过。

    直到目前为止,WSL64 下运行与调试 32 位程序仍然存在较大的困难。

    所以我选择在 VM 里调试 32 位程序 XD。

  • 参考:

2. WSL2

  • WSL2可以直接运行 32 位程序(感谢 @mudi-xu 的提醒),因此我们希望 WSL1 最好能在不重装原先 Ubuntu 系统的情况下,直接升级到 WSL2。

  • 但需要注意的是:WSL2只能在18917 之后的版本中才有。请自行运行命令 winver 以查看 OS 内部版本,如果版本低了,则需要升级一下 Windows OS。(现在我准备升级 windows 了 呜呜呜)

  • 具体操作如下

    • 首先,以管理员权限执行dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart启用“虚拟机平台”可选功能,之后重新启动计算机。
    • 计算机重启后,执行 wsl --list --verbose 以查看当前的 WSL 镜像及其版本。
    • 下载并安装适用于 x64 计算机的 WSL2 Linux 内核更新包
    • 之后,执行 wsl --set-version <SubSystemName> 2 以升级 WSL1 至 WSL2。这可能需要几分钟的时间。
    • 待升级完成后,可以再次执行 wsl --list --verbose以查看当前的 WSL 镜像 & 版本。
    • 最后执行 wsl --set-default-version 2 以设置之后安装的 Linux 子系统都安装到 WSL2 中。
  • 注意点:WSL2 与 VMware 15 不兼容。如果需要两者兼得则务必升级 VMware 至 16 版本

    升级VMware时无需卸载之前的版本,可以直接双击新安装包升级。

    升级时,务必勾选启用 Windows Hypervisor Platform,以支持 WSL2 和 VMware 的兼容。

  • WSL2在使用过程中,可能报错: 参考的对象类型不支持尝试的操作

    img

    有两种解决方法:

    • 第一种(不推荐):执行 netsh winsock reset,重置 winsock,并重启。但这种方法只能是临时性质的。

    • 第二种(推荐):下载 NoLsp.exe,并以管理员权限执行以下命令:

      1
      NoLsp.exe c:\windows\system32\wsl.exe

      等到出现 Success!之后就可以正常使用 WSL2了。

      img

    为什么解法2的方式如此独特呢?Proxifier 开发者发现:如果Winsock LSP DLL被加载到其进程中,则wsl.exe将显示此错误。因此最简单的解决方案是使用WSCSetApplicationCategory WinAPI调用wsl.exe来防止这种情况。

    这个调用在HKEY LOCAL MACHINE\SYSTEM\CurrentControlSet\Services\WinSock2\Parameters\AppId Catalog创建了一个wsl.exe的条目:

    img

    而这就是解法2的具体技术细节。

  • 参考

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2021 Kiprey
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~