GD32F130FXP6学习笔记十三:mdk优化掉不调用的函数和防止没有显式调用的函数被优化掉

一、优化掉没有调用的函数,减少程序空间

我做了下测试,在开一级优化下,我写了一个函数,但是没有调用,查看map文件发现

它仍然占用程序空间,所以我怀疑不是优化级别的事情。于是百度了下,发现要勾选C/C++的

One ELF Section per Function。什么是意思呢?就是每个文件的函数单独出一个连接文件,

这样连接的时候,那些没有调用的函数就被移除掉了。

GD32F130FXP6学习笔记十三:mdk优化掉不调用的函数和防止没有显式调用的函数被优化掉

查看编译后的map文件:

GD32F130FXP6学习笔记十三:mdk优化掉不调用的函数和防止没有显式调用的函数被优化掉


看到了没有?移除了。


二、mdk怎么实现IAR的__root效果

__root是指被修饰的变量或者函数在用户程序里面没有显式调用情况下,也不会被优化掉。

像一些系统配置和函数指针调用,就需要__root属性。

那么mdk怎么实现呢?查看了下编译器手册,并没有__root关键字,看了下连接器手册,有

--keep关键字。

官方说明:

--keep=section_id

ARM Compiler toolchain v5.02 for µVision Linker Reference  
Home >Linker command-line options > --keep=section_id

--keep=section_id

This option specifies input sections that must not be removed by unused section elimination.

GD32F130FXP6学习笔记十三:mdk优化掉不调用的函数和防止没有显式调用的函数被优化掉Syntax

--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 multiple 

For 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 is

For example, to keep the vect section from the vectors.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 specify section.

object

Specifies that the single input section from object is to be retained during unused section elimination. If you use this 

For example, you might use --keep=dspdata.o.

To keep the single input section from each of the objects that has a name starting withdsp, 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.

GD32F130FXP6学习笔记十三:mdk优化掉不调用的函数和防止没有显式调用的函数被优化掉Matching a symbol that has the same name as an object

If you name a symbol with the same name as an object, then --keep=symbol_id searches for a symbol that matchessymbol_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=symbol_id(). Therefore, to keep both the symbol and the object, 

specify --keep foo.o --keep foo.o().

GD32F130FXP6学习笔记十三:mdk优化掉不调用的函数和防止没有显式调用的函数被优化掉See also

Concepts

Using the Linker:

出处:

使用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。

GD32F130FXP6学习笔记十三:mdk优化掉不调用的函数和防止没有显式调用的函数被优化掉


编译后的文件:

GD32F130FXP6学习笔记十三:mdk优化掉不调用的函数和防止没有显式调用的函数被优化掉