Strip unused runtime functions which bloat executable (GCC)

泪湿孤枕 提交于 2019-12-03 14:02:40

You can never know what using one of library functions will pull in. Well, actually you probably can by creating call graph with one of the tools. So what part of c++ std library are you using?

Other than that, I have had success in removing unneeded function from executable by using two methods (none of this on ARM, but methods are not ARM specific):

  1. Compile with -ffunction-sections switch, then link with -gc-sections. This puts each function into it's own section and then tells linker to remove unused sections.
  2. Use link time optimization (-flto, see gcc manual for details). This lets compiler see "whole" program as if it was single source and will probably let it remove unused functions.

You are already using -Os, right?

Some CFLAGS:

If you don't use dynamic_cast or type_id in your code, try adding -fno-rtti. This will remove some amount of code relating to class hierarchies, and may remove several dozen bytes for each class in your code.

If you use throw() frequently in your function specifications, try adding -fnothrow-opt. This will encourage GCC to treat throw() as the more strict noexcept specification (from C++11), which will substantially reduce code size in many areas, since it will not have to construct exception frames.

As a companion to -fnothrow-opt, add -Wnoexcept. This will warn you when it finds a place to add throw() or noexcept, and further reduce the number of places exception frames must be constructed.

Also as a companion to above, replace all instances of new in your codebase (if any) with new (nothrow) and add -fcheck-new to your CFLAGS if necessary.

If you're not using threads, you might find a small benefit from -fno-threadsafe-statics, which removes code that performs thread-safe initialization of statics.

Linker

The new (well, for the last few years) binutils linker has a plugin called gold, which performs a number of link-time optimizations, including dead code removal. I don't know off-hand whether gold is supported on ARM yet, but this would be useful in substantially reducing the footprint of the standard library you import.

Why is this there, and how can I get rid of this stuff to reduce the .text section size of my target?

There might be (static) references for stuff linked in from the libstdc++, that will be instantiated no matter if they are called or referenced in the actually executed codepathes.
Carefully search for usage of #include statements that contain such reference declarations (e.g. #include <iostream>).

When libstdc++ is build during installation of GCC with different C++ compile flags as used for the finally intended target, there might be unwanted stuff linked in or being instantiated (e.g. the __gnu_cxx::recursive_init_error exception class despite usage of the -fno-exceptions flag). Use the --enable-cxx-flags configuration option to synchronize with the intended target compile flags when building the toolchain.

Also look carefully for unwanted/unexpected usage of certain STL classes in your codebase (e.g. std::string), they might compile and being linked without errors or warnings, despite certain features (e.g. new()) aren't really supported on your bare metal platform.

Are there more such stubs I can override?

Depending on how 'newlib' was build for the toolchain (see --en/disable-newlib-supplied-syscalls configuration option), it might be necessary to override certain or all stubs provided there.

Quick fixes

First, depending on limitations of your target - you may want to consider @Carl's recommendation above. We made the decision not to use C++ in our cortex m3 platform.

Second, Embedded development tip for reduction in size for C or C++ - kill floating point libs, in many many applications you can just use fixed point math, but some pull these in for the negotiable reasons (like desire to use "%f" in printf).

The hint your co-worker gave is probably very specific to your platform, probably it has a hardware watchdog? So it will be difficult for others who are not familiar with your hardware, code, or app to make such quick-fix recommendations.

Digging deeper

Did you actually add up the symbols of these libs and that is where you consume most of your .txt section?

The question may not be necessarily what you are not using from that library, but what you are. It is quite possible that the libraries you "demand" have their own dependencies.

It is a painful process (and maybe there are better ways) but if I were you I would try to remove the libraries you link and see what you really pull in (the STL headers may demand several of these symbols). If there are no surprises there, and your app only pulls in expected libraries you would need to dig in deeper:

Method 1: - Analyze the libstdc++ code (probably too long to jump into right away)

Methods 2: - I have never done this with C++, just with C libs, but the theory should hold - while removing linkage of libstdc++ - add in one object at a time from libstdc++, you can either build from code and use the object files explicitly or you can try and use tools such as ar (ar -t to list objects and ar -xv to extract). Note that I am not recommending that you cobble up your link command, just if you want to divide and conquer to see why these modules are demanded by the modules you actually use - at the end of the day you may be able to rebuild the library with a set of "without" flags. Reading the man pages or ar, nm, objdump would probably help in maybe automating some of this if it is taking too long, I have done stuff like that years ago so I don't have my cheat sheets handy.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!