在MinGW中构建GCC交叉编译器和GDB交叉调试器
前文 《C语言使用MinGW中的GCC生成平面(flat)二进制文件》中有介绍MinGW中使用GCC生成编写操作系统内核所需要的32位平面(flat)二进制文件。但是如果想要在Loader中使用C语言,即编译16位的汇编与C混合代码,就必须使用ELF格式才能转换成16位平面(flat)二进制文件。MinGW默认的GCC只能生成PE文件,不能生成ELF文件,而pei-386是无法转换成16位平面(flat)二进制文件的。
如果在link.ld中使用OUTPUT_FORMAT("pei-i386")
,会报错:
1mingw32/bin/ld.exe: unsupported PEI architecture: pei-i386
使用使用OUTPUT_FORMAT("binary")
,则会报:
1mingw32/bin/ld.exe: cannot perform PE operations on non PE output file 'loader.bin'
所以为了能使用MinGW编译16位汇编与C语言的混合代码,就必须编译一个交叉编译器。
下面笔者就以最新的GCC 12.1为例,介绍如何通过MinGW来构建GCC的交叉编译器。笔者的MinGW为MSYS2中的MinGW64。
一、下载Binutils
去 https://ftp.gnu.org/gnu/binutils/下载最新的binutils,目前最新的为 binutils-2.38.tar.xz
二、下载GCC
去 https://ftp.gnu.org/gnu/gcc/下载最新的GCC,目前最新的为 gcc-12.1.0.tar.gz
三、解压、编译
1.解压
在$HOME
下新建一个目录,比如src
,然后将下载的binutils-2.38.tar.xz
以及gcc-12.1.0.tar.gz
解压到$HOME/src
2.编译binutils
在编译之前后设置如下环境变量:
1export PREFIX="/opt/cross"
2export TARGET=i686-elf
3export PATH="$PREFIX/bin:$PATH"
如果是想编译成64位的则把TARGET设置为x86_64-elf
然后编译、安装binutils
:
1cd $HOME/src
2
3mkdir build-binutils
4cd build-binutils
5../binutils-2.38/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
6make
7make install
3. 编译、安装GCC
1cd $HOME/src
2
3# $PREFIX/bin目录必须在路径中,不然找不到as汇编器
4which -- $TARGET-as || echo $TARGET-as is not in the PATH
5
6# 进入GCC目录下载必要的依赖
7cd gcc-12.1.0/
8./contrib/download_prerequisites
9cd ..
10
11mkdir build-gcc
12cd build-gcc
13../gcc-12.1.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers
14make all-gcc
15make all-target-libgcc
16make install-gcc
17make install-target-libgcc
注意安装时的提示,后面可能会有用:
1----------------------------------------------------------------------
2Libraries have been installed in:
3 /opt/cross/libexec/gcc/i686-elf/12.1.0
4
5If you ever happen to want to link against installed libraries
6in a given directory, LIBDIR, you must either use libtool, and
7specify the full pathname of the library, or use the `-LLIBDIR'
8flag during linking and do at least one of the following:
9 - add LIBDIR to the `PATH' environment variable
10 during execution
11 - add LIBDIR to the `LD_RUN_PATH' environment variable
12 during linking
13 - use the `-LLIBDIR' linker flag
14
15See any operating system documentation about shared libraries for
16more information, such as the ld(1) and ld.so(8) manual pages.
17----------------------------------------------------------------------
编译完成后就可以在$HOME/opt/cross
目录下看到相应的程序了:
使用ld -V
查看支持的格式:
可以看到已经支持elf_i386了。Btw:从图中可以看到生成的文件都比较大,像i686-elf-lto-dump.exe
达370多M,可以通过使用strip命令删除调试信息来瘦身,在所有生成的exe目录使用:
1strip *.exe
以下是瘦身后的大小情况:
4.编译、安装GDB
下载最新的GDB,目前为gdb-12.1,设置好环境变量后,使用下面的命令进行编译,安装:
1$../gdb-12.1/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-multilib --disable-werror
2$make -j8
3$make install
5.设置路径
为了使用编译好的交叉编译器和调试器,需要添加到路径,编辑~/.bashrc
文件,添加一行:
1PATH=$PATH:/opt/cross/bin
如果编译遇到麻烦,或者不想自己编译也可以使用别人编译好的,参见: https://wiki.osdev.org/GCC_Cross-Compiler#Prebuilt Toolchains
有了交叉编译器和调试器,就可以使用MinGW构建16位应用程序了,同时也可以进行调试,有兴趣的话请关注后面的博文。
- 原文作者:Witton
- 原文链接:https://wittonbell.github.io/posts/2022/2022-07-06-在MinGW中构建GCC交叉编译器和GDB交叉调试器/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。