准备

  • 有问题的代码一份
  • 编译机一台
  • GDB(至少会start, c, b, bt, n, s, fin,建议会-tui, layout, info
  • (推荐)Instruction set manual
  • (推荐)Online cross referencer一个
  • (可选)参考书任意
  • 官方文档 重要!!!!!
  • 深入分析GCC

编译

安装

apt install -y curl mutt git autogen build-essential lsb-release zlib1g-dev texinfo bison flex expat libexpat1-dev libisl-dev libgmp-dev m4 dejagnu libmpc-dev libmpfr-dev

拉取

git clone https://github.com/gcc-mirror/gcc.git
# for cross building
git clone https://github.com/mirror/newlib-cygwin.git
git clone https://github.com/bminor/binutils-gdb

编译

只是调试gcc大可以只看asm输出结果。

mkdir gcc/build
cd gcc/build
../configure --prefix=/opt/<triplet> --program-prefix=<triplet>- --with-sysroot=/opt/<triplet>/<triplet> --target=<triplet> --with-gnu-as --with-gnu-ld --disable-nls --disable-threads --enable-languages=c,c++ --disable-multilib --enable-lto --disable-shared --with-newlib
make all-gcc "inhibit_libc=true"
sudo make install-gcc

以下是为了生成cross binary。

mkdir binutils-gdb/build
cd binutils-gdb/build
../configure --prefix=/opt/<triplet> --program-prefix=<triplet>- --with-sysroot=/opt/<triplet> --target=<triplet>
make
sudo make install
mkdir newlib-cygwin/build
cd newlib-cygwin/build
PATH=/opt/<triplet>/bin:"$PATH" ../configure --prefix=/opt/<triplet> --target=<triplet>
PATH=/opt/<triplet>/bin:"$PATH" make
PATH=/opt/<triplet>/bin:"$PATH" make install

cd gcc/build
../configure --prefix=/opt/<triplet> --program-prefix=<triplet>- --with-sysroot=/opt/<triplet>/<triplet> --target=<triplet> --with-gnu-as --with-gnu-ld --disable-nls --disable-threads --enable-languages=c,c++ --disable-multilib --enable-lto --disable-shared --with-newlib
make
make install
cd newlib-cygwin/build
PATH=/opt/<triplet>/bin:"$PATH" ../configure --prefix=/opt/<triplet> --target=<triplet>
PATH=/opt/<triplet>/bin:"$PATH" make
PATH=/opt/<triplet>/bin:"$PATH" make install

调试

export PATH=/opt/<triplet>/bin:"$PATH"

只看asm(对没编译stage2和libc是必须的):

<triplet>-gcc -S -o - test.c
  • GDB调试cc1:

https://gcc.gnu.org/wiki/DebuggingGCC

<triplet>-gcc <parameters> -wrapper gdb,--args

调试时pwd推荐位于gcc/gcc/

  • 编译过程:

编译过程

非常精炼的pass介绍:http://stffrdhrn.github.io/software/embedded/openrisc/2018/06/03/gcc_passes.html

  • 看pass:

https://gcc.gnu.org/onlinedocs/gcc/Developer-Options.html

  • IPA:-fdump-ipa-all
  • Tree:-fdump-tree-all

以上pass基本不用关心,有问题自会别有人修。以下是架构相关调试的重点。

  • RTL:-fdump-rtl-all

以上选项后再加-all(比如-fdump-ipa-all-all)输出更多信息。

  • 架构无关结果:-fdump-final-insns
  • 看不懂RTL -> https://gcc.gnu.org/onlinedocs/gccint/RTL.html
    • 尤其是SI/DI -> https://gcc.gnu.org/onlinedocs/gccint/Machine-Modes.html
    • 以及/u//v -> https://gcc.gnu.org/onlinedocs/gccint/Flags.html

Final轮已无调试信息,需看gcc/gcc/final.cc。有些源文件动态生成在gcc/build/gcc,尤其注意gcc/build/gcc/insn-*,基本会对应于gcc/gcc/config/<arch>