Contents

Sunday, 25. February 2007, 07:16:44

Linux内核源代码中有这么一个脚本文件:scripts/gcc-version.sh。它的主要代码如下:


9 compiler=”$*”
10
11 MAJOR=$(echo GNUC | $compiler -E -xc - | tail -n 1)
12 MINOR=$(echo GNUC_MINOR | $compiler -E -xc - | tail -n 1)
13 printf “%02d%02dn” $MAJOR $MINOR
14

从上面我们很容易看出它的用法,它要带一个参数,指明该平台上 GNU C编译器的命令(可能有些平台是cc)。它会给出GNU C编译器的版本号,以如下格式:XXYY,其中XX是主版本号,YY是次版本号,比如gcc-4.1的版本号就是0401。

这个脚本的实现很简单,它通过把GNU C编译器预先定义的宏GNUCGNUC_MINOR展开后交给编译器的预处理器处理,处理后其实就应该是想要的结果了,但gcc会自动在前面插入自己的一些东西,所以,要截取最后一行才是真正的结果。-E选项是指明只进行预处理,注意:如果没有-o,-E默认的输出是标准输出;-x选项是要指明所使用的语言,这里指明的是c;-是说明输入来自标准输入,这主要是照顾管道。

另一个和gcc相关的脚本是scripts/gcc-x86_64-has-stack-protector.sh,它用来测试x86_64(x86_64是AMD的,IA-64才是Intel的)上是不是有堆栈保护,代码如下:


3 echo “int foo(void) { char X[200]; return 3; }” | $1 -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - 2< /dev/null | grep -q “%gs”
4 if [ “$?” -eq “0” ] ; then
5 echo $2
6 fi

-fstack-protector选项是指明要检查堆栈是否会溢出,这是为了保护程序免于缓冲区溢出的攻击;-mcmodel=kernel是指明要为内核模式生成代码,Linux内核似乎要使用此选项。第3行的命令使用得更妙,还把中间命令的错误重定向到了/dev/null,而且还为grep开启了安静模式。似乎是从生成的汇编中找到”%gs”这个寄存器就说明有堆栈保护,但原理还是不明白;-(。

Contents