linux下intel编译器_Linux 下如何绕过编译器优化

同学们,告诉大家一个好消息,近日,泰晓科技与阅码场强强联合,首度推出码农自我修养之 「360° 剖析 Linux ELF」在线视频课程。由 吴章金 老师亲自授课,由浅入深地讲解程序加载、上下文传递、系统调用、内存布局、进程调度、代码调试以及程序退出全过程。如果您想进一步了解详情,请点击 “课程介绍”。

4789fda8f770fa87bd33cecce7bee501.png

以下为正文:

有同学在群里聊到编译器优化的事情,很多时候期望编译器默认做优化,但是有些场景是希望能绕过的,哪些呢?

这里举两个实实在在的例子。

第一个,在调试的时候,如果默认开启了优化,要关注的某个变量值,用 gdb 打印时可能会提示被优化掉了,会让人丈二和尚摸不着头脑。

第二个,就是某些场景,编译器并不理解背后的实际情况,比如说,连续往某个地址写两个值,编译器以为,这不是多此一举了,帮把最后一个写进去就好了,但是殊不知,这个地址可能是个硬件寄存器地址呢,写第一个,处理器调整一个状态,再写一个,再调整一个状态,两个都写完,才算完整,写不同的位有不同的含义。

1. 怎么去掉显式优化参数

对于第一个,通常不太需要去改整个内核,比如说,把整个 -O2/-Os 都拿掉,这时可能引起的莫名情况比去 debug 某个问题可能还要棘手。所以,可以有针对性的,只对某个文件做优化参数调整即可。

这个本质上是拿掉 CFLAGS 里头的优化参数,其实用替换就好了,但是可选的用法有:

文件级CFLAGS_REMOVE_xxx.o = -O2

arch/mips/kernel/Makefile:

1ifdef CONFIG_FUNCTION_TRACER
2CFLAGS_REMOVE_ftrace.o = -pg
3CFLAGS_REMOVE_early_printk.o = -pg
4CFLAGS_REMOVE_perf_event.o = -pg
5CFLAGS_REMOVE_perf_event_mipsxx.o = -pg
6endif

原理如下,就是从原始编译参数中 filter-out 掉特定参数:

1$ grep CFLAGS_REMOVE -ur linux-stable/scripts/Makefile.lib
2_c_flags       = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))

目录级KBUILD_CFLAGS := $(filter-out -O2, $(KBUILD_CFLAGS))

arch/mips/boot/compressed/Makefile:

1KBUILD_CFLAGS := $(filter-out -pg, $(KBUILD_CFLAGS))

自己主动 filter-out 掉。也可以直接调用脚本替换:

1KBUILD_CFLAGS := $(shell echo $(KBUILD_CFLAGS) | sed -e "s/-pg//")

当然,用 Makefile 内置的 filter-out 效率会高,只是方便大家理解逻辑。

怎么确认这个编译参数是否真地生效呢,有两种方法:

一种是直接在相应 Makefile 打印 KBUILD_CFLAGS,例如:$(error $(KBUILD_CFLAGS)),另外一种是 make /path/to/xxx.o V=1 查看。在 Linux Lab 里头可以用 make k-x /path/to/xxx.o V=1

除了直接拿掉,也可以考虑替换成 -Og,这个更适合调试需要。

2. 怎么去掉隐式优化

第二个,也来看看实例:

drivers/cpufreq/loongson2_cpufreq.c:

 1static void loongson2_cpu_wait(void) 2{
3        unsigned long flags;
4        u32 cpu_freq;
5
6        spin_lock_irqsave(&loongson2_wait_lock, flags);
7
8        cpu_freq = LOONGSON_CHIPCFG(0);
9        LOONGSON_CHIPCFG(0) &= ~0x7;    /* Put CPU into wait mode */
10        LOONGSON_CHIPCFG(0) = cpu_freq; /* Restore CPU state */
11
12        spin_unlock_irqrestore(&loongson2_wait_lock, flags);
13        local_irq_enable();
14}

上面中间三句,从 gcc 的角度来看,这不是傻嘛,啥也没做啊,又读又写是什么鬼,目标变量的值根本“没变”呢。原因是什么,这个背后的 LOONGSON_CHIPCFG(0) 是硬件寄存器地址,有它的时序意义,不同的位有不同的意义,写不同的值会有不同的动作。这个时候就得明确告诉 gcc:

arch/mips/include/asm/mach-loongson64/loongson.h:

1#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id]))

这种情况怎么确认呢?make /path/to/xxx.s,看看代码还在不在。在 “Linux Lab” 里头可以用 make k-x /path/to/xxx.s

点击文末左下角 “


315eb6ef2175554ba6e79b9515fe5d83.png

“泰晓科技”开通“Linux 知识星球”啦!  为答谢读者的关心,星主奉上免费体验卡一张,可以多人使用,也欢迎转赠给周边的朋友。

4c2d174c6ea0096674e14216b9c2deb7.png


0610693520d5514100906525dd69ae0c.png

467ae3859387c3acad363486bc959d5d.png关注“泰晓科技”!点“在看”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值