|
gcc -O3优化后readelf查看地址对齐方式【探讨】
[复制链接]
本帖最后由 lzwml 于 2014-12-15 10:59 编辑
为了给控制端加入的命令特性,我借鉴uboot的U_BOOT_CMD方式定义一个端,命名为W_BOOT_CMD,并在Uboot基础上添加些独有特性。但是我在地址对齐上遇到个bug,目前bug已经解决,发帖只是想和大家探讨关于gcc优化的问题。
如下代码:
W_BOOT_CMDn(cmd1,do_null,"shell help");
W_BOOT_CMDn(cmd2,do_null,"shell help");
W_BOOT_CMDn(cmd3,do_null,"shell help");
W_BOOT_CMDn(cmd4,do_null,"shell help");
连接脚本没使用4字节对齐
-------------省略---------------------------------------------------------------------------------------
. = ALIGN(4);
.rodata : {*(.rodata)}
. = .; 从这个段开始不对其
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = .;
__w_boot_cmd_start = .;
.w_boot_cmd : { *(.w_boot_cmd) }
__w_boot_cmd_end = .;
-------------省略--------------------------------------------------------------------------------
测试1:编译后采用不优化(或者-O1优化),然后用readelf -s release/download.elf | grep __w查看"__w_boot_cmd_xxx"相关内容,下面的内容与我期望的相同,代码在这里
405: 3000997c 0 NOTYPE GLOBAL DEFAULT ABS __w_boot_cmd_start
428: 300099a0 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd4
479: 30009994 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd3
525: 300099ac 0 NOTYPE GLOBAL DEFAULT ABS __w_boot_cmd_end
535: 30009988 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd2
590: 3000997c 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd1
我所定义的结构体的长度是12字节,这4个命令的段地址依次排列start-->cmd1-->cmd2-->cmd3-->cmd4--end,并且start地址和cmd1一样
测试2:编译采用-O3(其实-O2优化就出现以下错误),
352: 3000d5fe 0 NOTYPE GLOBAL DEFAULT ABS __w_boot_cmd_start
375: 3000d600 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd4
426: 3000d60c 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd3
472: 3000d630 0 NOTYPE GLOBAL DEFAULT ABS __w_boot_cmd_end
482: 3000d618 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd2
537: 3000d624 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd1
这4个命令的段地址依次排列start-->cmd4-->cmd3-->cmd2-->cmd1--end,并且start不地址不等于cmd4地址相差2字节,编译后地址分配顺序和C语言代码里的相反。就是因为start相当于野指针,所以我的代码跑到这里就飞了。
解决方案测试3:将连接脚本修改成4字节对齐,依旧采用-O3优化
. = ALIGN(4);
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__w_boot_cmd_start = .;
.w_boot_cmd : { *(.w_boot_cmd) }
__w_boot_cmd_end = .;
352: 3000d600 0 NOTYPE GLOBAL DEFAULT ABS __w_boot_cmd_start
375: 3000d600 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd4
426: 3000d60c 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd3
472: 3000d630 0 NOTYPE GLOBAL DEFAULT ABS __w_boot_cmd_end
482: 3000d618 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd2
537: 3000d624 12 OBJECT GLOBAL DEFAULT 8 __w_boot_cmd_cmd1
这4个命令的段地址依次排列start-->cmd4-->cmd3-->cmd2-->cmd1--end,现在start和cmd4相等,虽然和预期的start等于cmd1有出入,但地址是对齐的不影响我的代码。
测试4:更改c文件编译顺序
原始的c代码编译顺序是:
模块1.c 模块2.c 模块3.c 我自己的模仿uboot写的shell.c 一个编译后很大的模块.c
改成
模块1.c 模块2.c 模块3.c 一个编译后很大的模块.c 我自己的模仿uboot写的shell.c
接着在链接脚本里不使用4字节对齐声明,采用-O3优化编译。代码对齐方式和测试3一样。
问题:
1、有什么办法能在优化的情况下,命令地址顺序依旧是start-->cmd1-->cmd2-->cmd3-->cmd4--end。
2、uboot默认采用-Os优化(不知道优化级别怎么样man的解释看不懂),于是我用-O3优化测试,他的命令顺序同-Os一样,暂时没找到uboot的Makefie哪个编译选项能达到此目的
3、大家对采用-O3优化代码时有什么调试经验,或者有什么技巧可以避免优化后的可执行文件出现不可预料情况。
4、在采用-O2即以上优化时readelf -S 看到会生成一个.rodata.str1.4段,不知道是干什么用的
|
|