GD32F130FXP6学习笔记十三:mdk优化掉不调用的函数和防止没有显式调用的函数被优化掉
一、优化掉没有调用的函数,减少程序空间
我做了下测试,在开一级优化下,我写了一个函数,但是没有调用,查看map文件发现
它仍然占用程序空间,所以我怀疑不是优化级别的事情。于是百度了下,发现要勾选C/C++的
One ELF Section per Function。什么是意思呢?就是每个文件的函数单独出一个连接文件,
这样连接的时候,那些没有调用的函数就被移除掉了。
查看编译后的map文件:
看到了没有?移除了。
二、mdk怎么实现IAR的__root效果
__root是指被修饰的变量或者函数在用户程序里面没有显式调用情况下,也不会被优化掉。
像一些系统配置和函数指针调用,就需要__root属性。
那么mdk怎么实现呢?查看了下编译器手册,并没有__root关键字,看了下连接器手册,有
--keep关键字。
官方说明:
--keep=section_id
|
|||
Home >Linker command-line options > --keep=section_id |
This option specifies input sections that must not be removed by unused section elimination.
--keep=section_id
Where section_id
is one of the following:
symbol
-
Specifies that an input section defining
symbol
is to be retained during unused section elimination. If multipleFor example, you might use
--keep=int_handler
.To keep all sections that define a symbol ending in
_handler
, use--keep=*_handler
. -
definitions of
symbol
exist,armlink generates an error message. object
(section
)-
Specifies that
section
fromobject
is to be retained during unused section elimination. If a single instance ofsection
isFor example, to keep the
vect
section from thevectors.o
object use:--keep=vectors.o(vect)
To keep all sections from the
vectors.o
object where the first three characters of the name of the sections arevec
, -
use:
--keep=vectors.o(vec*)
-
generated, you can omit
section
, for example,file.o()
. Otherwise, you must specifysection
. object
-
Specifies that the single input section from
object
is to be retained during unused section elimination. If you use thisFor example, you might use
--keep=dspdata.o
.To keep the single input section from each of the objects that has a name starting with
dsp
, use--keep=dsp*.o
. -
short form and there is more than one input section in
object
, the linker generates an error message.
All forms of the section_id
argument can contain the*
and
?
wild characters. Matching is case-insensitive, even on hosts
with case-sensitive file naming. For example:
-
--keep foo.o(Premier*)
causes the entire match forPremier*
to be case-insensitive -
--keep foo.o(Premier)
causes a case-sensitive match for the string Premier.
Use *.o
to match all object files. Use
*
to match all object files and libraries.
You can specify multiple --keep
options on the command line.
If you name a symbol with the same name as an object, then
--keep=
searches for a symbol that matchessymbol_id
symbol_id
:
-
If a symbol is found, it matches the symbol.
-
If no symbol is found, it matches the object.
You can force --keep
to match an object with
--keep=
. Therefore, to keep both the symbol and the object, symbol_id
()
specify --keep foo.o --keep foo.o()
.
使用mdk编程,假如有一个有用的函数你定义了但是没有显式的调用,mdk在默认方式下,将会把这
个函数从整个程序总删除掉,以节省ROM.
比如,你在ROM的0x00002000处定位了一个函数,假设为void test(void),然后使用函数指针来调用它:
void (*UserProgram)(); //函数指针
UserProgram = (void (*)()) (0x00002000);//定位到指定的入口地址0x00002000
(*UserProgram)();//调用test()函数
这样做的本意是调用test()函数,但编译器并不知情,它仍会按照默认的指令将test函数给整个优化掉,因为它
觉得test()函数根本没有被调用,这个时候,虽然(*UserProgram)();仍会执行,但内容与初衷已经大相径庭.
能否让编译器不自动优化test这个函数?
当然有,就是使用链接器命令:--keep=section_id 此选项指定删除未使用节时不能删除的输入节。
其中 section_id 是以下项之一:
symbol 指定在删除未使用节时保留定义 symbol 的输入节。 如果 symbol 存在多个定义,则 armlink
将生成一则错误消息。
例如,您可能使用 --keep=int_handler。若要保留定义以 _handler 结尾的符号的所有节,请
使用--keep=*_handler。object(section)指定在删除未使用节时保留 object 中的 section。 例如,
若要保留vectors.o 对象的 vect 节,请使用: -- keep=vectors.o(vect)若要保留 vectors.o 对象
中节名称的前三个字母是 vec 的所有节,请使用:--keep=vectors.o(vec*)由于我的程序test()函数是
单独放在一个文件里(entry.c)的,所以我在linker标签栏下的Misc controls编辑框中输入--keep=entry.o。
编译后的文件: