xref: /aosp_15_r20/external/pigweed/docs/size_optimizations.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _docs-size-optimizations:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker==================
4*61c4878aSAndroid Build Coastguard WorkerSize optimizations
5*61c4878aSAndroid Build Coastguard Worker==================
6*61c4878aSAndroid Build Coastguard WorkerThis page contains recommendations for optimizing the size of embedded software
7*61c4878aSAndroid Build Coastguard Workerincluding its memory and code footprints.
8*61c4878aSAndroid Build Coastguard Worker
9*61c4878aSAndroid Build Coastguard WorkerThese recommendations are subject to change as the C++ standard and compilers
10*61c4878aSAndroid Build Coastguard Workerevolve, and as the authors continue to gain more knowledge and experience in
11*61c4878aSAndroid Build Coastguard Workerthis area. If you disagree with recommendations, please discuss them with the
12*61c4878aSAndroid Build Coastguard WorkerPigweed team, as we're always looking to improve the guide or correct any
13*61c4878aSAndroid Build Coastguard Workerinaccuracies.
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Worker---------------------------------
16*61c4878aSAndroid Build Coastguard WorkerCompile Time Constant Expressions
17*61c4878aSAndroid Build Coastguard Worker---------------------------------
18*61c4878aSAndroid Build Coastguard WorkerThe use of `constexpr <https://en.cppreference.com/w/cpp/language/constexpr>`_
19*61c4878aSAndroid Build Coastguard Workerand soon with C++20
20*61c4878aSAndroid Build Coastguard Worker`consteval <https://en.cppreference.com/w/cpp/language/consteval>`_ can enable
21*61c4878aSAndroid Build Coastguard Workeryou to evaluate the value of a function or variable more at compile-time rather
22*61c4878aSAndroid Build Coastguard Workerthan only at run-time. This can often not only result in smaller sizes but also
23*61c4878aSAndroid Build Coastguard Workeroften times more efficient, faster execution.
24*61c4878aSAndroid Build Coastguard Worker
25*61c4878aSAndroid Build Coastguard WorkerWe highly encourage using this aspect of C++, however there is one caveat: be
26*61c4878aSAndroid Build Coastguard Workercareful in marking functions constexpr in APIs which cannot be easily changed
27*61c4878aSAndroid Build Coastguard Workerin the future unless you can prove that for all time and all platforms, the
28*61c4878aSAndroid Build Coastguard Workercomputation can actually be done at compile time. This is because there is no
29*61c4878aSAndroid Build Coastguard Worker"mutable" escape hatch for constexpr.
30*61c4878aSAndroid Build Coastguard Worker
31*61c4878aSAndroid Build Coastguard WorkerSee the :doc:`embedded_cpp_guide` for more detail.
32*61c4878aSAndroid Build Coastguard Worker
33*61c4878aSAndroid Build Coastguard Worker---------
34*61c4878aSAndroid Build Coastguard WorkerTemplates
35*61c4878aSAndroid Build Coastguard Worker---------
36*61c4878aSAndroid Build Coastguard WorkerThe compiler implements templates by generating a separate version of the
37*61c4878aSAndroid Build Coastguard Workerfunction for each set of types it is instantiated with. This can increase code
38*61c4878aSAndroid Build Coastguard Workersize significantly.
39*61c4878aSAndroid Build Coastguard Worker
40*61c4878aSAndroid Build Coastguard WorkerBe careful when instantiating non-trivial template functions with multiple
41*61c4878aSAndroid Build Coastguard Workertypes.
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard WorkerConsider splitting templated interfaces into multiple layers so that more of the
44*61c4878aSAndroid Build Coastguard Workerimplementation can be shared between different instantiations. A more advanced
45*61c4878aSAndroid Build Coastguard Workerform is to share common logic internally by using default sentinel template
46*61c4878aSAndroid Build Coastguard Workerargument value and ergo instantation such as ``pw::Vector``'s
47*61c4878aSAndroid Build Coastguard Worker``size_t kMaxSize = vector_impl::kGeneric`` or ``pw::span``'s
48*61c4878aSAndroid Build Coastguard Worker``size_t Extent = dynamic_extent``.
49*61c4878aSAndroid Build Coastguard Worker
50*61c4878aSAndroid Build Coastguard Worker-----------------
51*61c4878aSAndroid Build Coastguard WorkerVirtual Functions
52*61c4878aSAndroid Build Coastguard Worker-----------------
53*61c4878aSAndroid Build Coastguard WorkerVirtual functions provide for runtime polymorphism. Unless runtime polymorphism
54*61c4878aSAndroid Build Coastguard Workeris required, virtual functions should be avoided. Virtual functions require a
55*61c4878aSAndroid Build Coastguard Workervirtual table and a pointer to it in each instance, which all increases RAM
56*61c4878aSAndroid Build Coastguard Workerusage and requires extra instructions at each call site. Virtual functions can
57*61c4878aSAndroid Build Coastguard Workeralso inhibit compiler optimizations, since the compiler may not be able to tell
58*61c4878aSAndroid Build Coastguard Workerwhich functions will actually be invoked. This can prevent linker garbage
59*61c4878aSAndroid Build Coastguard Workercollection, resulting in unused functions being linked into a binary.
60*61c4878aSAndroid Build Coastguard Worker
61*61c4878aSAndroid Build Coastguard WorkerWhen runtime polymorphism is required, virtual functions should be considered.
62*61c4878aSAndroid Build Coastguard WorkerC alternatives, such as a struct of function pointers, could be used instead,
63*61c4878aSAndroid Build Coastguard Workerbut these approaches may offer no performance advantage while sacrificing
64*61c4878aSAndroid Build Coastguard Workerflexibility and ease of use.
65*61c4878aSAndroid Build Coastguard Worker
66*61c4878aSAndroid Build Coastguard WorkerOnly use virtual functions when runtime polymorphism is needed. Lastly try to
67*61c4878aSAndroid Build Coastguard Workeravoid templated virtual interfaces which can compound the cost by instantiating
68*61c4878aSAndroid Build Coastguard Workermany virtual tables.
69*61c4878aSAndroid Build Coastguard Worker
70*61c4878aSAndroid Build Coastguard WorkerDevirtualization
71*61c4878aSAndroid Build Coastguard Worker================
72*61c4878aSAndroid Build Coastguard WorkerWhen you do use virtual functions, try to keep devirtualization in mind. You can
73*61c4878aSAndroid Build Coastguard Workermake it easier on the compiler and linker by declaring class definitions as
74*61c4878aSAndroid Build Coastguard Worker``final`` to improve the odds. This can help significantly depending on your
75*61c4878aSAndroid Build Coastguard Workertoolchain.
76*61c4878aSAndroid Build Coastguard Worker
77*61c4878aSAndroid Build Coastguard WorkerIf you're interested in more details,
78*61c4878aSAndroid Build Coastguard Worker`this is an interesting deep dive <https://quuxplusone.github.io/blog/2021/02/15/devirtualization/>`_.
79*61c4878aSAndroid Build Coastguard Worker
80*61c4878aSAndroid Build Coastguard Worker---------------------------------------------------------
81*61c4878aSAndroid Build Coastguard WorkerInitialization, Constructors, Finalizers, and Destructors
82*61c4878aSAndroid Build Coastguard Worker---------------------------------------------------------
83*61c4878aSAndroid Build Coastguard WorkerConstructors
84*61c4878aSAndroid Build Coastguard Worker============
85*61c4878aSAndroid Build Coastguard WorkerWhere possible consider making your constructors constexpr to reduce their
86*61c4878aSAndroid Build Coastguard Workercosts. This also enables global instances to be eligible for ``.data`` or if
87*61c4878aSAndroid Build Coastguard Workerall zeros for ``.bss`` section placement.
88*61c4878aSAndroid Build Coastguard Worker
89*61c4878aSAndroid Build Coastguard WorkerStatic Destructors And Finalizers
90*61c4878aSAndroid Build Coastguard Worker=================================
91*61c4878aSAndroid Build Coastguard WorkerFor many embedded projects, cleaning up after the program is not a requirement,
92*61c4878aSAndroid Build Coastguard Workermeaning the exit functions including any finalizers registered through
93*61c4878aSAndroid Build Coastguard Worker``atexit``, ``at_quick_exit``, and static destructors can all be removed to
94*61c4878aSAndroid Build Coastguard Workerreduce the size.
95*61c4878aSAndroid Build Coastguard Worker
96*61c4878aSAndroid Build Coastguard WorkerThe exact mechanics for disabling static destructors depends on your toolchain.
97*61c4878aSAndroid Build Coastguard Worker
98*61c4878aSAndroid Build Coastguard WorkerSee the `Ignored Finalizer and Destructor Registration`_ section below for
99*61c4878aSAndroid Build Coastguard Workerfurther details regarding disabling registration of functions to be run at exit
100*61c4878aSAndroid Build Coastguard Workervia ``atexit`` and ``at_quick_exit``.
101*61c4878aSAndroid Build Coastguard Worker
102*61c4878aSAndroid Build Coastguard WorkerClang
103*61c4878aSAndroid Build Coastguard Worker-----
104*61c4878aSAndroid Build Coastguard WorkerWith modern versions of Clang you can simply use ``-fno-C++-static-destructors``
105*61c4878aSAndroid Build Coastguard Workerand you are done.
106*61c4878aSAndroid Build Coastguard Worker
107*61c4878aSAndroid Build Coastguard WorkerGCC with newlib-nano
108*61c4878aSAndroid Build Coastguard Worker--------------------
109*61c4878aSAndroid Build Coastguard WorkerWith GCC this is more complicated. For example with GCC for ARM Cortex M devices
110*61c4878aSAndroid Build Coastguard Workerusing ``newlib-nano`` you are forced to tackle the problem in two stages.
111*61c4878aSAndroid Build Coastguard Worker
112*61c4878aSAndroid Build Coastguard WorkerFirst, there are the destructors for the static global objects. These can be
113*61c4878aSAndroid Build Coastguard Workerplaced in the ``.fini_array`` and ``.fini`` input sections through the use of
114*61c4878aSAndroid Build Coastguard Workerthe ``-fno-use-cxa-atexit`` GCC flag, assuming ``newlib-nano`` was configured
115*61c4878aSAndroid Build Coastguard Workerwith ``HAVE_INITFINI_ARAY_SUPPORT``. The two input sections can then be
116*61c4878aSAndroid Build Coastguard Workerexplicitly discarded in the linker script through the use of the special
117*61c4878aSAndroid Build Coastguard Worker``/DISCARD/`` output section:
118*61c4878aSAndroid Build Coastguard Worker
119*61c4878aSAndroid Build Coastguard Worker.. code-block:: text
120*61c4878aSAndroid Build Coastguard Worker
121*61c4878aSAndroid Build Coastguard Worker   /DISCARD/ : {
122*61c4878aSAndroid Build Coastguard Worker   /* The finalizers are never invoked when the target shuts down and ergo
123*61c4878aSAndroid Build Coastguard Worker    * can be discarded. These include C++ global static destructors and C
124*61c4878aSAndroid Build Coastguard Worker    * designated finalizers. */
125*61c4878aSAndroid Build Coastguard Worker   *(.fini_array);
126*61c4878aSAndroid Build Coastguard Worker   *(.fini);
127*61c4878aSAndroid Build Coastguard Worker
128*61c4878aSAndroid Build Coastguard WorkerSecond, there are the destructors for the scoped static objects, frequently
129*61c4878aSAndroid Build Coastguard Workerreferred to as Meyer's Singletons. With the Itanium ABI these use
130*61c4878aSAndroid Build Coastguard Worker``__cxa_atexit`` to register destruction on the fly. However, if
131*61c4878aSAndroid Build Coastguard Worker``-fno-use-cxa-atexit`` is used with GCC and ``newlib-nano`` these will appear
132*61c4878aSAndroid Build Coastguard Workeras ``__tcf_`` prefixed symbols, for example ``__tcf_0``.
133*61c4878aSAndroid Build Coastguard Worker
134*61c4878aSAndroid Build Coastguard WorkerThere's `an interesting proposal (P1247R0) <http://wg21.link/p1247r0>`_ to
135*61c4878aSAndroid Build Coastguard Workerenable ``[[no_destroy]]`` attributes to C++ which would be tempting to use here.
136*61c4878aSAndroid Build Coastguard WorkerAlas this is not an option yet. As mentioned in the proposal one way to remove
137*61c4878aSAndroid Build Coastguard Workerthe destructors from these scoped statics is to wrap it in a templated wrapper
138*61c4878aSAndroid Build Coastguard Workerwhich uses placement new.
139*61c4878aSAndroid Build Coastguard Worker
140*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
141*61c4878aSAndroid Build Coastguard Worker
142*61c4878aSAndroid Build Coastguard Worker   #include <type_traits>
143*61c4878aSAndroid Build Coastguard Worker
144*61c4878aSAndroid Build Coastguard Worker   template <class T>
145*61c4878aSAndroid Build Coastguard Worker   class NoDestroy {
146*61c4878aSAndroid Build Coastguard Worker    public:
147*61c4878aSAndroid Build Coastguard Worker     template <class... Ts>
148*61c4878aSAndroid Build Coastguard Worker     NoDestroy(Ts&&... ts) {
149*61c4878aSAndroid Build Coastguard Worker       new (&static_) T(std::forward<Ts>(ts)...);
150*61c4878aSAndroid Build Coastguard Worker     }
151*61c4878aSAndroid Build Coastguard Worker
152*61c4878aSAndroid Build Coastguard Worker     T& get() { return reinterpret_cast<T&>(static_); }
153*61c4878aSAndroid Build Coastguard Worker
154*61c4878aSAndroid Build Coastguard Worker    private:
155*61c4878aSAndroid Build Coastguard Worker     std::aligned_storage_t<sizeof(T), alignof(T)> static_;
156*61c4878aSAndroid Build Coastguard Worker   };
157*61c4878aSAndroid Build Coastguard Worker
158*61c4878aSAndroid Build Coastguard WorkerThis can then be used as follows to instantiate scoped statics where the
159*61c4878aSAndroid Build Coastguard Workerdestructor will never be invoked and ergo will not be linked in.
160*61c4878aSAndroid Build Coastguard Worker
161*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
162*61c4878aSAndroid Build Coastguard Worker
163*61c4878aSAndroid Build Coastguard Worker   Foo& GetFoo() {
164*61c4878aSAndroid Build Coastguard Worker     static NoDestroy<Foo> foo(foo_args);
165*61c4878aSAndroid Build Coastguard Worker     return foo.get();
166*61c4878aSAndroid Build Coastguard Worker   }
167*61c4878aSAndroid Build Coastguard Worker
168*61c4878aSAndroid Build Coastguard Worker-------
169*61c4878aSAndroid Build Coastguard WorkerStrings
170*61c4878aSAndroid Build Coastguard Worker-------
171*61c4878aSAndroid Build Coastguard Worker
172*61c4878aSAndroid Build Coastguard WorkerTokenization
173*61c4878aSAndroid Build Coastguard Worker============
174*61c4878aSAndroid Build Coastguard WorkerInstead of directly using strings and printf, consider using
175*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_tokenizer` to replace strings and printf-style formatted strings
176*61c4878aSAndroid Build Coastguard Workerwith binary tokens during compilation. This can reduce the code size, memory
177*61c4878aSAndroid Build Coastguard Workerusage, I/O traffic, and even CPU utilization by replacing snprintf calls with
178*61c4878aSAndroid Build Coastguard Workersimple tokenization code.
179*61c4878aSAndroid Build Coastguard Worker
180*61c4878aSAndroid Build Coastguard WorkerBe careful when using string arguments with tokenization as these still result
181*61c4878aSAndroid Build Coastguard Workerin a string in your binary which is appended to your token at run time.
182*61c4878aSAndroid Build Coastguard Worker
183*61c4878aSAndroid Build Coastguard WorkerString Formatting
184*61c4878aSAndroid Build Coastguard Worker=================
185*61c4878aSAndroid Build Coastguard WorkerThe formatted output family of printf functions in ``<cstdio>`` are quite
186*61c4878aSAndroid Build Coastguard Workerexpensive from a code size point of view and they often rely on malloc. Instead,
187*61c4878aSAndroid Build Coastguard Workerwhere tokenization cannot be used, consider using :ref:`module-pw_string`'s
188*61c4878aSAndroid Build Coastguard Workerutilities.
189*61c4878aSAndroid Build Coastguard Worker
190*61c4878aSAndroid Build Coastguard WorkerRemoving all printf functions often saves more than 5KiB of code size on ARM
191*61c4878aSAndroid Build Coastguard WorkerCortex M devices using ``newlib-nano``.
192*61c4878aSAndroid Build Coastguard Worker
193*61c4878aSAndroid Build Coastguard WorkerLogging & Asserting
194*61c4878aSAndroid Build Coastguard Worker===================
195*61c4878aSAndroid Build Coastguard WorkerUsing tokenized backends for logging and asserting such as
196*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_log_tokenized` coupled with :ref:`module-pw_assert_log` can
197*61c4878aSAndroid Build Coastguard Workerdrastically reduce the costs. However, even with this approach there remains a
198*61c4878aSAndroid Build Coastguard Workercallsite cost which can add up due to arguments and including metadata.
199*61c4878aSAndroid Build Coastguard Worker
200*61c4878aSAndroid Build Coastguard WorkerTry to avoid string arguments and reduce unnecessary extra arguments where
201*61c4878aSAndroid Build Coastguard Workerpossible. And consider adjusting log levels to compile out debug or even info
202*61c4878aSAndroid Build Coastguard Workerlogs as code stabilizes and matures.
203*61c4878aSAndroid Build Coastguard Worker
204*61c4878aSAndroid Build Coastguard WorkerFuture Plans
205*61c4878aSAndroid Build Coastguard Worker------------
206*61c4878aSAndroid Build Coastguard WorkerGoing forward Pigweed is evaluating extra configuration options to do things
207*61c4878aSAndroid Build Coastguard Workersuch as dropping log arguments for certain log levels and modules to give users
208*61c4878aSAndroid Build Coastguard Workerfiner grained control in trading off diagnostic value and the size cost.
209*61c4878aSAndroid Build Coastguard Worker
210*61c4878aSAndroid Build Coastguard Worker----------------------------------
211*61c4878aSAndroid Build Coastguard WorkerThreading and Synchronization Cost
212*61c4878aSAndroid Build Coastguard Worker----------------------------------
213*61c4878aSAndroid Build Coastguard Worker
214*61c4878aSAndroid Build Coastguard WorkerLighterweight Signaling Primatives
215*61c4878aSAndroid Build Coastguard Worker==================================
216*61c4878aSAndroid Build Coastguard WorkerConsider using ``pw::sync::ThreadNotification`` instead of semaphores as they
217*61c4878aSAndroid Build Coastguard Workercan be implemented using more efficient RTOS specific signaling primitives. For
218*61c4878aSAndroid Build Coastguard Workerexample on FreeRTOS they can be backed by direct task notifications which are
219*61c4878aSAndroid Build Coastguard Workermore than 10x smaller than semaphores while also being faster.
220*61c4878aSAndroid Build Coastguard Worker
221*61c4878aSAndroid Build Coastguard WorkerThreads and their stack sizes
222*61c4878aSAndroid Build Coastguard Worker=============================
223*61c4878aSAndroid Build Coastguard WorkerAlthough synchronous APIs are incredibly portable and often easier to reason
224*61c4878aSAndroid Build Coastguard Workerabout, it is often easy to forget the large stack cost this design paradigm
225*61c4878aSAndroid Build Coastguard Workercomes with. We highly recommend watermarking your stacks to reduce wasted
226*61c4878aSAndroid Build Coastguard Workermemory.
227*61c4878aSAndroid Build Coastguard Worker
228*61c4878aSAndroid Build Coastguard WorkerOur snapshot integration for RTOSes such as :ref:`module-pw_thread_freertos` and
229*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_thread_embos` come with built in support to report stack
230*61c4878aSAndroid Build Coastguard Workerwatermarks for threads if enabled in the kernel.
231*61c4878aSAndroid Build Coastguard Worker
232*61c4878aSAndroid Build Coastguard WorkerIn addition, consider using asynchronous design patterns such as Active Objects
233*61c4878aSAndroid Build Coastguard Workerwhich can use :ref:`module-pw_work_queue` or similar asynchronous dispatch work
234*61c4878aSAndroid Build Coastguard Workerqueues to effectively permit the sharing of stack allocations.
235*61c4878aSAndroid Build Coastguard Worker
236*61c4878aSAndroid Build Coastguard WorkerBuffer Sizing
237*61c4878aSAndroid Build Coastguard Worker=============
238*61c4878aSAndroid Build Coastguard WorkerWe'd be remiss not to mention the sizing of the various buffers that may exist
239*61c4878aSAndroid Build Coastguard Workerin your application. You could consider watermarking them with
240*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_metric`. You may also be able to adjust their servicing interval
241*61c4878aSAndroid Build Coastguard Workerand priority, but do not forget to keep the ingress burst sizes and scheduling
242*61c4878aSAndroid Build Coastguard Workerjitter into account.
243*61c4878aSAndroid Build Coastguard Worker
244*61c4878aSAndroid Build Coastguard Worker----------------------------
245*61c4878aSAndroid Build Coastguard WorkerStandard C and C++ libraries
246*61c4878aSAndroid Build Coastguard Worker----------------------------
247*61c4878aSAndroid Build Coastguard WorkerToolchains are typically distributed with their preferred standard C library and
248*61c4878aSAndroid Build Coastguard Workerstandard C++ library of choice for the target platform.
249*61c4878aSAndroid Build Coastguard Worker
250*61c4878aSAndroid Build Coastguard WorkerAlthough you do not always have a choice in what standard C library and what
251*61c4878aSAndroid Build Coastguard Workerstandard C++ library is used or even how it's compiled, stay vigilant for common
252*61c4878aSAndroid Build Coastguard Workersources of bloat.
253*61c4878aSAndroid Build Coastguard Worker
254*61c4878aSAndroid Build Coastguard WorkerAssert
255*61c4878aSAndroid Build Coastguard Worker======
256*61c4878aSAndroid Build Coastguard WorkerThe standard C library should provides the ``assert`` function or macro which
257*61c4878aSAndroid Build Coastguard Workermay be internally used even if your application does not invoke it directly.
258*61c4878aSAndroid Build Coastguard WorkerAlthough this can be disabled through ``NDEBUG`` there typically is not a
259*61c4878aSAndroid Build Coastguard Workerportable way of replacing the ``assert(condition)`` implementation without
260*61c4878aSAndroid Build Coastguard Workerconfiguring and recompiling your standard C library.
261*61c4878aSAndroid Build Coastguard Worker
262*61c4878aSAndroid Build Coastguard WorkerHowever, you can consider replacing the implementation at link time with a
263*61c4878aSAndroid Build Coastguard Workercheaper implementation. For example ``newlib-nano``, which comes with the
264*61c4878aSAndroid Build Coastguard Worker``GNU Arm Embedded Toolchain``, often has an expensive ``__assert_func``
265*61c4878aSAndroid Build Coastguard Workerimplementation which uses ``fiprintf`` to print to ``stderr`` before invoking
266*61c4878aSAndroid Build Coastguard Worker``abort()``. This can be replaced with a simple ``PW_CRASH`` invocation which
267*61c4878aSAndroid Build Coastguard Workercan save several kilobytes in case ``fiprintf`` isn't used elsewhere.
268*61c4878aSAndroid Build Coastguard Worker
269*61c4878aSAndroid Build Coastguard WorkerOne option to remove this bloat is to use ``--wrap`` at link time to replace
270*61c4878aSAndroid Build Coastguard Workerthese implementations. As an example in GN you could replace it with the
271*61c4878aSAndroid Build Coastguard Workerfollowing ``BUILD.gn`` file:
272*61c4878aSAndroid Build Coastguard Worker
273*61c4878aSAndroid Build Coastguard Worker.. code-block:: text
274*61c4878aSAndroid Build Coastguard Worker
275*61c4878aSAndroid Build Coastguard Worker   import("//build_overrides/pigweed.gni")
276*61c4878aSAndroid Build Coastguard Worker
277*61c4878aSAndroid Build Coastguard Worker   import("$dir_pw_build/target_types.gni")
278*61c4878aSAndroid Build Coastguard Worker
279*61c4878aSAndroid Build Coastguard Worker   # Wraps the function called by newlib's implementation of assert from stdlib.h.
280*61c4878aSAndroid Build Coastguard Worker   #
281*61c4878aSAndroid Build Coastguard Worker   # When using this, we suggest injecting :newlib_assert via pw_build_LINK_DEPS.
282*61c4878aSAndroid Build Coastguard Worker   config("wrap_newlib_assert") {
283*61c4878aSAndroid Build Coastguard Worker     ldflags = [ "-Wl,--wrap=__assert_func" ]
284*61c4878aSAndroid Build Coastguard Worker   }
285*61c4878aSAndroid Build Coastguard Worker
286*61c4878aSAndroid Build Coastguard Worker   # Implements the function called by newlib's implementation of assert from
287*61c4878aSAndroid Build Coastguard Worker   # stdlib.h which invokes __assert_func unless NDEBUG is defined.
288*61c4878aSAndroid Build Coastguard Worker   pw_source_set("wrapped_newlib_assert") {
289*61c4878aSAndroid Build Coastguard Worker     sources = [ "wrapped_newlib_assert.cc" ]
290*61c4878aSAndroid Build Coastguard Worker     deps = [
291*61c4878aSAndroid Build Coastguard Worker       "$dir_pw_assert:check",
292*61c4878aSAndroid Build Coastguard Worker       "$dir_pw_preprocessor",
293*61c4878aSAndroid Build Coastguard Worker     ]
294*61c4878aSAndroid Build Coastguard Worker   }
295*61c4878aSAndroid Build Coastguard Worker
296*61c4878aSAndroid Build Coastguard WorkerAnd a ``wrapped_newlib_assert.cc`` source file implementing the wrapped assert
297*61c4878aSAndroid Build Coastguard Workerfunction:
298*61c4878aSAndroid Build Coastguard Worker
299*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
300*61c4878aSAndroid Build Coastguard Worker
301*61c4878aSAndroid Build Coastguard Worker   #include "pw_assert/check.h"
302*61c4878aSAndroid Build Coastguard Worker   #include "pw_preprocessor/compiler.h"
303*61c4878aSAndroid Build Coastguard Worker
304*61c4878aSAndroid Build Coastguard Worker   // This is defined by <cassert>
305*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap___assert_func(const char*,
306*61c4878aSAndroid Build Coastguard Worker                                                     int,
307*61c4878aSAndroid Build Coastguard Worker                                                     const char*,
308*61c4878aSAndroid Build Coastguard Worker                                                     const char*) {
309*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("libc assert() failure");
310*61c4878aSAndroid Build Coastguard Worker   }
311*61c4878aSAndroid Build Coastguard Worker
312*61c4878aSAndroid Build Coastguard Worker
313*61c4878aSAndroid Build Coastguard WorkerIgnored Finalizer and Destructor Registration
314*61c4878aSAndroid Build Coastguard Worker=============================================
315*61c4878aSAndroid Build Coastguard WorkerEven if no cleanup is done during shutdown for your target, shutdown functions
316*61c4878aSAndroid Build Coastguard Workersuch as ``atexit``, ``at_quick_exit``, and ``__cxa_atexit`` can sometimes not be
317*61c4878aSAndroid Build Coastguard Workerlinked out. This may be due to vendor code or perhaps using scoped statics, also
318*61c4878aSAndroid Build Coastguard Workerknown as Meyer's Singletons.
319*61c4878aSAndroid Build Coastguard Worker
320*61c4878aSAndroid Build Coastguard WorkerThe registration of these destructors and finalizers may include locks, malloc,
321*61c4878aSAndroid Build Coastguard Workerand more depending on your standard C library and its configuration.
322*61c4878aSAndroid Build Coastguard Worker
323*61c4878aSAndroid Build Coastguard WorkerOne option to remove this bloat is to use ``--wrap`` at link time to replace
324*61c4878aSAndroid Build Coastguard Workerthese implementations with ones which do nothing. As an example in GN you could
325*61c4878aSAndroid Build Coastguard Workerreplace it with the following ``BUILD.gn`` file:
326*61c4878aSAndroid Build Coastguard Worker
327*61c4878aSAndroid Build Coastguard Worker.. code-block:: text
328*61c4878aSAndroid Build Coastguard Worker
329*61c4878aSAndroid Build Coastguard Worker   import("//build_overrides/pigweed.gni")
330*61c4878aSAndroid Build Coastguard Worker
331*61c4878aSAndroid Build Coastguard Worker   import("$dir_pw_build/target_types.gni")
332*61c4878aSAndroid Build Coastguard Worker
333*61c4878aSAndroid Build Coastguard Worker   config("wrap_atexit") {
334*61c4878aSAndroid Build Coastguard Worker     ldflags = [
335*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=atexit",
336*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=at_quick_exit",
337*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=__cxa_atexit",
338*61c4878aSAndroid Build Coastguard Worker     ]
339*61c4878aSAndroid Build Coastguard Worker   }
340*61c4878aSAndroid Build Coastguard Worker
341*61c4878aSAndroid Build Coastguard Worker   # Implements atexit, at_quick_exit, and __cxa_atexit from stdlib.h with noop
342*61c4878aSAndroid Build Coastguard Worker   # versions for targets which do not cleanup during exit and quick_exit.
343*61c4878aSAndroid Build Coastguard Worker   #
344*61c4878aSAndroid Build Coastguard Worker   # This removes any dependencies which may exist in your existing libc.
345*61c4878aSAndroid Build Coastguard Worker   # Although this removes the ability for things such as Meyer's Singletons,
346*61c4878aSAndroid Build Coastguard Worker   # i.e. non-global statics, to register destruction function it does not permit
347*61c4878aSAndroid Build Coastguard Worker   # them to be garbage collected by the linker.
348*61c4878aSAndroid Build Coastguard Worker   pw_source_set("wrapped_noop_atexit") {
349*61c4878aSAndroid Build Coastguard Worker     sources = [ "wrapped_noop_atexit.cc" ]
350*61c4878aSAndroid Build Coastguard Worker   }
351*61c4878aSAndroid Build Coastguard Worker
352*61c4878aSAndroid Build Coastguard WorkerAnd a ``wrapped_noop_atexit.cc`` source file implementing the noop functions:
353*61c4878aSAndroid Build Coastguard Worker
354*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
355*61c4878aSAndroid Build Coastguard Worker
356*61c4878aSAndroid Build Coastguard Worker   // These two are defined by <cstdlib>.
357*61c4878aSAndroid Build Coastguard Worker   extern "C" int __wrap_atexit(void (*)(void)) { return 0; }
358*61c4878aSAndroid Build Coastguard Worker   extern "C" int __wrap_at_quick_exit(void (*)(void)) { return 0; }
359*61c4878aSAndroid Build Coastguard Worker
360*61c4878aSAndroid Build Coastguard Worker   // This function is part of the Itanium C++ ABI, there is no header which
361*61c4878aSAndroid Build Coastguard Worker   // provides this.
362*61c4878aSAndroid Build Coastguard Worker   extern "C" int __wrap___cxa_atexit(void (*)(void*), void*, void*) { return 0; }
363*61c4878aSAndroid Build Coastguard Worker
364*61c4878aSAndroid Build Coastguard WorkerUnexpected Bloat in Disabled STL Exceptions
365*61c4878aSAndroid Build Coastguard Worker===========================================
366*61c4878aSAndroid Build Coastguard WorkerThe GCC
367*61c4878aSAndroid Build Coastguard Worker`manual <https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_exceptions.html>`_
368*61c4878aSAndroid Build Coastguard Workerrecommends using ``-fno-exceptions`` along with ``-fno-unwind-tables`` to
369*61c4878aSAndroid Build Coastguard Workerdisable exceptions and any associated overhead. This should replace all throw
370*61c4878aSAndroid Build Coastguard Workerstatements with calls to ``abort()``.
371*61c4878aSAndroid Build Coastguard Worker
372*61c4878aSAndroid Build Coastguard WorkerHowever, what we've noticed with the GCC and ``libstdc++`` is that there is a
373*61c4878aSAndroid Build Coastguard Workerrisk that the STL will still throw exceptions when the application is compiled
374*61c4878aSAndroid Build Coastguard Workerwith ``-fno-exceptions`` and there is no way for you to catch them. In theory,
375*61c4878aSAndroid Build Coastguard Workerthis is not unsafe because the unhandled exception will invoke ``abort()`` via
376*61c4878aSAndroid Build Coastguard Worker``std::terminate()``. This can occur because the libraries such as
377*61c4878aSAndroid Build Coastguard Worker``libstdc++.a`` may not have been compiled with ``-fno-exceptions`` even though
378*61c4878aSAndroid Build Coastguard Workeryour application is linked against it.
379*61c4878aSAndroid Build Coastguard Worker
380*61c4878aSAndroid Build Coastguard WorkerSee
381*61c4878aSAndroid Build Coastguard Worker`this <https://blog.mozilla.org/nnethercote/2011/01/18/the-dangers-of-fno-exceptions/>`_
382*61c4878aSAndroid Build Coastguard Workerfor more information.
383*61c4878aSAndroid Build Coastguard Worker
384*61c4878aSAndroid Build Coastguard WorkerUnfortunately there can be significant overhead surrounding these throw call
385*61c4878aSAndroid Build Coastguard Workersites in the ``std::__throw_*`` helper functions. These implementations such as
386*61c4878aSAndroid Build Coastguard Worker``std::__throw_out_of_range_fmt(const char*, ...)`` and
387*61c4878aSAndroid Build Coastguard Workertheir snprintf and ergo malloc dependencies can very quickly add up to many
388*61c4878aSAndroid Build Coastguard Workerkilobytes of unnecessary overhead.
389*61c4878aSAndroid Build Coastguard Worker
390*61c4878aSAndroid Build Coastguard WorkerOne option to remove this bloat while also making sure that the exceptions will
391*61c4878aSAndroid Build Coastguard Workeractually result in an effective ``abort()`` is to use ``--wrap`` at link time to
392*61c4878aSAndroid Build Coastguard Workerreplace these implementations with ones which simply call ``PW_CRASH``.
393*61c4878aSAndroid Build Coastguard Worker
394*61c4878aSAndroid Build Coastguard WorkerAs an example in GN you could replace it with the following ``BUILD.gn`` file,
395*61c4878aSAndroid Build Coastguard Workernote that the mangled names must be used:
396*61c4878aSAndroid Build Coastguard Worker
397*61c4878aSAndroid Build Coastguard Worker.. code-block:: text
398*61c4878aSAndroid Build Coastguard Worker
399*61c4878aSAndroid Build Coastguard Worker   import("//build_overrides/pigweed.gni")
400*61c4878aSAndroid Build Coastguard Worker
401*61c4878aSAndroid Build Coastguard Worker   import("$dir_pw_build/target_types.gni")
402*61c4878aSAndroid Build Coastguard Worker
403*61c4878aSAndroid Build Coastguard Worker   # Wraps the std::__throw_* functions called by GNU ISO C++ Library regardless
404*61c4878aSAndroid Build Coastguard Worker   # of whether "-fno-exceptions" is specified.
405*61c4878aSAndroid Build Coastguard Worker   #
406*61c4878aSAndroid Build Coastguard Worker   # When using this, we suggest injecting :wrapped_libstdc++_functexcept via
407*61c4878aSAndroid Build Coastguard Worker   # pw_build_LINK_DEPS.
408*61c4878aSAndroid Build Coastguard Worker   config("wrap_libstdc++_functexcept") {
409*61c4878aSAndroid Build Coastguard Worker     ldflags = [
410*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt21__throw_bad_exceptionv",
411*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt17__throw_bad_allocv",
412*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt16__throw_bad_castv",
413*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt18__throw_bad_typeidv",
414*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt19__throw_logic_errorPKc",
415*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt20__throw_domain_errorPKc",
416*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt24__throw_invalid_argumentPKc",
417*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt20__throw_length_errorPKc",
418*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt20__throw_out_of_rangePKc",
419*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt24__throw_out_of_range_fmtPKcz",
420*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt21__throw_runtime_errorPKc",
421*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt19__throw_range_errorPKc",
422*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt22__throw_overflow_errorPKc",
423*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt23__throw_underflow_errorPKc",
424*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt19__throw_ios_failurePKc",
425*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt19__throw_ios_failurePKci",
426*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt20__throw_system_errori",
427*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt20__throw_future_errori",
428*61c4878aSAndroid Build Coastguard Worker       "-Wl,--wrap=_ZSt25__throw_bad_function_callv",
429*61c4878aSAndroid Build Coastguard Worker     ]
430*61c4878aSAndroid Build Coastguard Worker   }
431*61c4878aSAndroid Build Coastguard Worker
432*61c4878aSAndroid Build Coastguard Worker   # Implements the std::__throw_* functions called by GNU ISO C++ Library
433*61c4878aSAndroid Build Coastguard Worker   # regardless of whether "-fno-exceptions" is specified with PW_CRASH.
434*61c4878aSAndroid Build Coastguard Worker   pw_source_set("wrapped_libstdc++_functexcept") {
435*61c4878aSAndroid Build Coastguard Worker     sources = [ "wrapped_libstdc++_functexcept.cc" ]
436*61c4878aSAndroid Build Coastguard Worker     deps = [
437*61c4878aSAndroid Build Coastguard Worker       "$dir_pw_assert:check",
438*61c4878aSAndroid Build Coastguard Worker       "$dir_pw_preprocessor",
439*61c4878aSAndroid Build Coastguard Worker     ]
440*61c4878aSAndroid Build Coastguard Worker   }
441*61c4878aSAndroid Build Coastguard Worker
442*61c4878aSAndroid Build Coastguard WorkerAnd a ``wrapped_libstdc++_functexcept.cc`` source file implementing each
443*61c4878aSAndroid Build Coastguard Workerwrapped and mangled ``std::__throw_*`` function:
444*61c4878aSAndroid Build Coastguard Worker
445*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
446*61c4878aSAndroid Build Coastguard Worker
447*61c4878aSAndroid Build Coastguard Worker   #include "pw_assert/check.h"
448*61c4878aSAndroid Build Coastguard Worker   #include "pw_preprocessor/compiler.h"
449*61c4878aSAndroid Build Coastguard Worker
450*61c4878aSAndroid Build Coastguard Worker   // These are all wrapped implementations of the throw functions provided by
451*61c4878aSAndroid Build Coastguard Worker   // libstdc++'s bits/functexcept.h which are not needed when "-fno-exceptions"
452*61c4878aSAndroid Build Coastguard Worker   // is used.
453*61c4878aSAndroid Build Coastguard Worker
454*61c4878aSAndroid Build Coastguard Worker   // std::__throw_bad_exception(void)
455*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt21__throw_bad_exceptionv() {
456*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_bad_exception");
457*61c4878aSAndroid Build Coastguard Worker   }
458*61c4878aSAndroid Build Coastguard Worker
459*61c4878aSAndroid Build Coastguard Worker   // std::__throw_bad_alloc(void)
460*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt17__throw_bad_allocv() {
461*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_bad_alloc");
462*61c4878aSAndroid Build Coastguard Worker   }
463*61c4878aSAndroid Build Coastguard Worker
464*61c4878aSAndroid Build Coastguard Worker   // std::__throw_bad_cast(void)
465*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt16__throw_bad_castv() {
466*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_bad_cast");
467*61c4878aSAndroid Build Coastguard Worker   }
468*61c4878aSAndroid Build Coastguard Worker
469*61c4878aSAndroid Build Coastguard Worker   // std::__throw_bad_typeid(void)
470*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt18__throw_bad_typeidv() {
471*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_bad_typeid");
472*61c4878aSAndroid Build Coastguard Worker   }
473*61c4878aSAndroid Build Coastguard Worker
474*61c4878aSAndroid Build Coastguard Worker   // std::__throw_logic_error(const char*)
475*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt19__throw_logic_errorPKc(const char*) {
476*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_logic_error");
477*61c4878aSAndroid Build Coastguard Worker   }
478*61c4878aSAndroid Build Coastguard Worker
479*61c4878aSAndroid Build Coastguard Worker   // std::__throw_domain_error(const char*)
480*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt20__throw_domain_errorPKc(const char*) {
481*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_domain_error");
482*61c4878aSAndroid Build Coastguard Worker   }
483*61c4878aSAndroid Build Coastguard Worker
484*61c4878aSAndroid Build Coastguard Worker   // std::__throw_invalid_argument(const char*)
485*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt24__throw_invalid_argumentPKc(
486*61c4878aSAndroid Build Coastguard Worker       const char*) {
487*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_invalid_argument");
488*61c4878aSAndroid Build Coastguard Worker   }
489*61c4878aSAndroid Build Coastguard Worker
490*61c4878aSAndroid Build Coastguard Worker   // std::__throw_length_error(const char*)
491*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt20__throw_length_errorPKc(const char*) {
492*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_length_error");
493*61c4878aSAndroid Build Coastguard Worker   }
494*61c4878aSAndroid Build Coastguard Worker
495*61c4878aSAndroid Build Coastguard Worker   // std::__throw_out_of_range(const char*)
496*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt20__throw_out_of_rangePKc(const char*) {
497*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_out_of_range");
498*61c4878aSAndroid Build Coastguard Worker   }
499*61c4878aSAndroid Build Coastguard Worker
500*61c4878aSAndroid Build Coastguard Worker   // std::__throw_out_of_range_fmt(const char*, ...)
501*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt24__throw_out_of_range_fmtPKcz(
502*61c4878aSAndroid Build Coastguard Worker       const char*, ...) {
503*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_out_of_range");
504*61c4878aSAndroid Build Coastguard Worker   }
505*61c4878aSAndroid Build Coastguard Worker
506*61c4878aSAndroid Build Coastguard Worker   // std::__throw_runtime_error(const char*)
507*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt21__throw_runtime_errorPKc(
508*61c4878aSAndroid Build Coastguard Worker       const char*) {
509*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_runtime_error");
510*61c4878aSAndroid Build Coastguard Worker   }
511*61c4878aSAndroid Build Coastguard Worker
512*61c4878aSAndroid Build Coastguard Worker   // std::__throw_range_error(const char*)
513*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt19__throw_range_errorPKc(const char*) {
514*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_range_error");
515*61c4878aSAndroid Build Coastguard Worker   }
516*61c4878aSAndroid Build Coastguard Worker
517*61c4878aSAndroid Build Coastguard Worker   // std::__throw_overflow_error(const char*)
518*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt22__throw_overflow_errorPKc(
519*61c4878aSAndroid Build Coastguard Worker       const char*) {
520*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_overflow_error");
521*61c4878aSAndroid Build Coastguard Worker   }
522*61c4878aSAndroid Build Coastguard Worker
523*61c4878aSAndroid Build Coastguard Worker   // std::__throw_underflow_error(const char*)
524*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt23__throw_underflow_errorPKc(
525*61c4878aSAndroid Build Coastguard Worker       const char*) {
526*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_underflow_error");
527*61c4878aSAndroid Build Coastguard Worker   }
528*61c4878aSAndroid Build Coastguard Worker
529*61c4878aSAndroid Build Coastguard Worker   // std::__throw_ios_failure(const char*)
530*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt19__throw_ios_failurePKc(const char*) {
531*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_ios_failure");
532*61c4878aSAndroid Build Coastguard Worker   }
533*61c4878aSAndroid Build Coastguard Worker
534*61c4878aSAndroid Build Coastguard Worker   // std::__throw_ios_failure(const char*, int)
535*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt19__throw_ios_failurePKci(const char*,
536*61c4878aSAndroid Build Coastguard Worker                                                                     int) {
537*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_ios_failure");
538*61c4878aSAndroid Build Coastguard Worker   }
539*61c4878aSAndroid Build Coastguard Worker
540*61c4878aSAndroid Build Coastguard Worker   // std::__throw_system_error(int)
541*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt20__throw_system_errori(int) {
542*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_system_error");
543*61c4878aSAndroid Build Coastguard Worker   }
544*61c4878aSAndroid Build Coastguard Worker
545*61c4878aSAndroid Build Coastguard Worker   // std::__throw_future_error(int)
546*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt20__throw_future_errori(int) {
547*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_future_error");
548*61c4878aSAndroid Build Coastguard Worker   }
549*61c4878aSAndroid Build Coastguard Worker
550*61c4878aSAndroid Build Coastguard Worker   // std::__throw_bad_function_call(void)
551*61c4878aSAndroid Build Coastguard Worker   extern "C" PW_NO_RETURN void __wrap__ZSt25__throw_bad_function_callv() {
552*61c4878aSAndroid Build Coastguard Worker     PW_CRASH("std::throw_bad_function_call");
553*61c4878aSAndroid Build Coastguard Worker   }
554*61c4878aSAndroid Build Coastguard Worker
555*61c4878aSAndroid Build Coastguard Worker---------------------------------
556*61c4878aSAndroid Build Coastguard WorkerCompiler and Linker Optimizations
557*61c4878aSAndroid Build Coastguard Worker---------------------------------
558*61c4878aSAndroid Build Coastguard Worker
559*61c4878aSAndroid Build Coastguard WorkerCompiler Optimization Options
560*61c4878aSAndroid Build Coastguard Worker=============================
561*61c4878aSAndroid Build Coastguard WorkerDon't forget to configure your compiler to optimize for size if needed. With
562*61c4878aSAndroid Build Coastguard WorkerClang this is ``-Oz`` and with GCC this can be done via ``-Os``. The GN
563*61c4878aSAndroid Build Coastguard Workertoolchains provided through :ref:`module-pw_toolchain` which are optimized for
564*61c4878aSAndroid Build Coastguard Workersize are suffixed with ``*_size_optimized``.
565*61c4878aSAndroid Build Coastguard Worker
566*61c4878aSAndroid Build Coastguard WorkerGarbage collect function and data sections
567*61c4878aSAndroid Build Coastguard Worker==========================================
568*61c4878aSAndroid Build Coastguard WorkerBy default the linker will place all functions in an object within the same
569*61c4878aSAndroid Build Coastguard Workerlinker "section" (e.g. ``.text``). With Clang and GCC you can use
570*61c4878aSAndroid Build Coastguard Worker``-ffunction-sections`` and ``-fdata-sections`` to use a unique "section" for
571*61c4878aSAndroid Build Coastguard Workereach object (e.g. ``.text.do_foo_function``). This permits you to pass
572*61c4878aSAndroid Build Coastguard Worker``--gc-sections`` to the linker to cull any unused sections which were not
573*61c4878aSAndroid Build Coastguard Workerreferenced.
574*61c4878aSAndroid Build Coastguard Worker
575*61c4878aSAndroid Build Coastguard WorkerTo see what sections were garbage collected you can pass ``--print-gc-sections``
576*61c4878aSAndroid Build Coastguard Workerto the linker so it prints out what was removed.
577*61c4878aSAndroid Build Coastguard Worker
578*61c4878aSAndroid Build Coastguard WorkerThe GN toolchains provided through :ref:`module-pw_toolchain` are configured to
579*61c4878aSAndroid Build Coastguard Workerdo this by default.
580*61c4878aSAndroid Build Coastguard Worker
581*61c4878aSAndroid Build Coastguard WorkerFunction Inlining
582*61c4878aSAndroid Build Coastguard Worker=================
583*61c4878aSAndroid Build Coastguard WorkerDon't forget to expose trivial functions such as member accessors as inline
584*61c4878aSAndroid Build Coastguard Workerdefinitions in the header. The compiler and linker can make the trade-off on
585*61c4878aSAndroid Build Coastguard Workerwhether the function should be actually inlined or not based on your
586*61c4878aSAndroid Build Coastguard Workeroptimization settings, however this at least gives it the option. Note that LTO
587*61c4878aSAndroid Build Coastguard Workercan inline functions which are not defined in headers.
588*61c4878aSAndroid Build Coastguard Worker
589*61c4878aSAndroid Build Coastguard WorkerWe stand by the
590*61c4878aSAndroid Build Coastguard Worker`Google style guide <https://google.github.io/styleguide/cppguide.html#Inline_Functions>`_
591*61c4878aSAndroid Build Coastguard Workerto recommend considering this for simple functions which are 10 lines or less.
592*61c4878aSAndroid Build Coastguard Worker
593*61c4878aSAndroid Build Coastguard WorkerLink Time Optimization (LTO)
594*61c4878aSAndroid Build Coastguard Worker============================
595*61c4878aSAndroid Build Coastguard Worker**Summary: LTO can decrase your binary size, at a cost: LTO makes debugging
596*61c4878aSAndroid Build Coastguard Workerharder, interacts poorly with linker scripts, and makes crash reports less
597*61c4878aSAndroid Build Coastguard Workerinformative. We advise only enabling LTO when absolutely necessary.**
598*61c4878aSAndroid Build Coastguard Worker
599*61c4878aSAndroid Build Coastguard WorkerLink time optimization (LTO) moves some optimizations from the individual
600*61c4878aSAndroid Build Coastguard Workercompile steps to the final link step, to enable optimizing across translation
601*61c4878aSAndroid Build Coastguard Workerunit boundaries.
602*61c4878aSAndroid Build Coastguard Worker
603*61c4878aSAndroid Build Coastguard WorkerLTO can both increase performance and reduce binary size for embedded projects.
604*61c4878aSAndroid Build Coastguard WorkerThis appears to be a strict improvement; and one might think enabling LTO at
605*61c4878aSAndroid Build Coastguard Workerall times is the best approach. However, this is not the case; in practice, LTO
606*61c4878aSAndroid Build Coastguard Workeris a trade-off.
607*61c4878aSAndroid Build Coastguard Worker
608*61c4878aSAndroid Build Coastguard Worker**LTO benefits**
609*61c4878aSAndroid Build Coastguard Worker
610*61c4878aSAndroid Build Coastguard Worker* **Reduces binary size** - When compiling with size-shrinking flags like
611*61c4878aSAndroid Build Coastguard Worker  ``-Oz``, some function call overhead can be eliminated, and code paths might
612*61c4878aSAndroid Build Coastguard Worker  be eliminated by the optimizer after inlining. This can include critical
613*61c4878aSAndroid Build Coastguard Worker  abstraction removal like devirtualization.
614*61c4878aSAndroid Build Coastguard Worker* **Improves performance** - When code is inlined, the optimizer can better
615*61c4878aSAndroid Build Coastguard Worker  reduce the number of instructions. When code is smaller, the instruction
616*61c4878aSAndroid Build Coastguard Worker  cache has better hit ratio leading to better performance. In some cases,
617*61c4878aSAndroid Build Coastguard Worker  entire function calls are eliminated.
618*61c4878aSAndroid Build Coastguard Worker
619*61c4878aSAndroid Build Coastguard Worker**LTO costs**
620*61c4878aSAndroid Build Coastguard Worker
621*61c4878aSAndroid Build Coastguard Worker* **LTO interacts poorly with linker scripts** - Production embedded projects
622*61c4878aSAndroid Build Coastguard Worker  often have complicated linker scripts to control the physical layout of code
623*61c4878aSAndroid Build Coastguard Worker  and data on the device. For example, you may want to put performance critical
624*61c4878aSAndroid Build Coastguard Worker  audio codec functions into the fast tightly coupled (TCM) memory region.
625*61c4878aSAndroid Build Coastguard Worker  However, LTO can interact with linker script requirements in strange ways,
626*61c4878aSAndroid Build Coastguard Worker  like inappropriately inlining code that was manually placed into other
627*61c4878aSAndroid Build Coastguard Worker  functions in the wrong region; leading to hard-to-understand bugs.
628*61c4878aSAndroid Build Coastguard Worker* **Debugging LTO binaries is harder** - LTO increases the differences between
629*61c4878aSAndroid Build Coastguard Worker  the machine code and the source code. This makes stepping through source code
630*61c4878aSAndroid Build Coastguard Worker  in a debugger confusing, since the instruction pointer can hop around in
631*61c4878aSAndroid Build Coastguard Worker  confusing ways.
632*61c4878aSAndroid Build Coastguard Worker* **Crash reports for LTO binaries can be misleading** - Just as with
633*61c4878aSAndroid Build Coastguard Worker  debugging, LTO'd binaries can produce confusing stacks in crash reports.
634*61c4878aSAndroid Build Coastguard Worker* **LTO significantly increases build times** - The compilation model is
635*61c4878aSAndroid Build Coastguard Worker  different when LTO is enabled, since individual translation unit compilations
636*61c4878aSAndroid Build Coastguard Worker  (`.cc` --> `.o`) files now produce LLVM- or GCC- IR instead of native machine
637*61c4878aSAndroid Build Coastguard Worker  code; machine code is only generated at the link phase. This makes the final
638*61c4878aSAndroid Build Coastguard Worker  link step take significantly longer. Since any source changes will result in
639*61c4878aSAndroid Build Coastguard Worker  a link step, developer velocity is reduced due to the slow compile time.
640*61c4878aSAndroid Build Coastguard Worker
641*61c4878aSAndroid Build Coastguard WorkerHow to enable LTO
642*61c4878aSAndroid Build Coastguard Worker-----------------
643*61c4878aSAndroid Build Coastguard WorkerOn GCC and Clang LTO is enabled by passing ``-flto`` to both the compiler
644*61c4878aSAndroid Build Coastguard Workerand the linker. On GCC ``-fdevirtualize-at-ltrans`` enables more aggressive
645*61c4878aSAndroid Build Coastguard Workerdevirtualization.
646*61c4878aSAndroid Build Coastguard Worker
647*61c4878aSAndroid Build Coastguard WorkerOur recommendation
648*61c4878aSAndroid Build Coastguard Worker------------------
649*61c4878aSAndroid Build Coastguard Worker* Disable LTO unless absolutely necessary; e.g. due to lack of space.
650*61c4878aSAndroid Build Coastguard Worker* When enabling LTO, carefully and thoroughly test the resulting binary.
651*61c4878aSAndroid Build Coastguard Worker* Check that crash reports are still useful under LTO for your product.
652*61c4878aSAndroid Build Coastguard Worker
653*61c4878aSAndroid Build Coastguard WorkerDisabling Scoped Static Initialization Locks
654*61c4878aSAndroid Build Coastguard Worker============================================
655*61c4878aSAndroid Build Coastguard WorkerC++11 requires that scoped static objects are initialized in a thread-safe
656*61c4878aSAndroid Build Coastguard Workermanner. This also means that scoped statics, i.e. Meyer's Singletons, be
657*61c4878aSAndroid Build Coastguard Workerthread-safe. Unfortunately this rarely is the case on embedded targets. For
658*61c4878aSAndroid Build Coastguard Workerexample with GCC on an ARM Cortex M device if you test for this you will
659*61c4878aSAndroid Build Coastguard Workerdiscover that instead the program crashes as reentrant initialization is
660*61c4878aSAndroid Build Coastguard Workerdetected through the use of guard variables.
661*61c4878aSAndroid Build Coastguard Worker
662*61c4878aSAndroid Build Coastguard WorkerWith GCC and Clang, ``-fno-threadsafe-statics`` can be used to remove the global
663*61c4878aSAndroid Build Coastguard Workerlock which often does not work for embedded targets. Note that this leaves the
664*61c4878aSAndroid Build Coastguard Workerguard variables in place which ensure that reentrant initialization continues to
665*61c4878aSAndroid Build Coastguard Workercrash.
666*61c4878aSAndroid Build Coastguard Worker
667*61c4878aSAndroid Build Coastguard WorkerBe careful when using this option in case you are relying on threadsafe
668*61c4878aSAndroid Build Coastguard Workerinitialization of statics and the global locks were functional for your target.
669*61c4878aSAndroid Build Coastguard Worker
670*61c4878aSAndroid Build Coastguard WorkerTriaging Unexpectedly Linked In Functions
671*61c4878aSAndroid Build Coastguard Worker=========================================
672*61c4878aSAndroid Build Coastguard WorkerLastly as a tip if you cannot figure out why a function is being linked in you
673*61c4878aSAndroid Build Coastguard Workercan consider:
674*61c4878aSAndroid Build Coastguard Worker
675*61c4878aSAndroid Build Coastguard Worker* Using ``--wrap`` with the linker to remove the implementation, resulting in a
676*61c4878aSAndroid Build Coastguard Worker  link failure which typically calls out which calling function can no longer be
677*61c4878aSAndroid Build Coastguard Worker  linked.
678*61c4878aSAndroid Build Coastguard Worker* With GCC, you can use ``-fcallgraph-info`` to visualize or otherwise inspect
679*61c4878aSAndroid Build Coastguard Worker  the callgraph to figure out who is calling what.
680*61c4878aSAndroid Build Coastguard Worker* Sometimes symbolizing the address can resolve what a function is for. For
681*61c4878aSAndroid Build Coastguard Worker  example if you are using ``newlib-nano`` along with ``-fno-use-cxa-atexit``,
682*61c4878aSAndroid Build Coastguard Worker  scoped static destructors are prefixed ``__tcf_*``. To figure out object these
683*61c4878aSAndroid Build Coastguard Worker  destructor functions are associated with, you can use ``llvm-symbolizer`` or
684*61c4878aSAndroid Build Coastguard Worker  ``addr2line`` and these will often print out the related object's name.
685*61c4878aSAndroid Build Coastguard Worker
686*61c4878aSAndroid Build Coastguard WorkerSorting input sections by alignment
687*61c4878aSAndroid Build Coastguard Worker=========================================
688*61c4878aSAndroid Build Coastguard Worker
689*61c4878aSAndroid Build Coastguard WorkerLinker scripts often contain input section wildcard patterns to specify which
690*61c4878aSAndroid Build Coastguard Workerinput sections should be placed in each output section. For example, say a
691*61c4878aSAndroid Build Coastguard Workerlinker script contains a sections command like the following:
692*61c4878aSAndroid Build Coastguard Worker
693*61c4878aSAndroid Build Coastguard Worker.. code-block:: text
694*61c4878aSAndroid Build Coastguard Worker
695*61c4878aSAndroid Build Coastguard Worker   .text : { *(.init*) *(.text*) }
696*61c4878aSAndroid Build Coastguard Worker
697*61c4878aSAndroid Build Coastguard WorkerBy default, the GCC and Clang linkers will place symbols matched by each
698*61c4878aSAndroid Build Coastguard Workerwildcard pattern in the order they are seen at link-time. The linker will insert
699*61c4878aSAndroid Build Coastguard Workerpadding bytes as necessary to satisfy the alignment requirements of each symbol.
700*61c4878aSAndroid Build Coastguard Worker
701*61c4878aSAndroid Build Coastguard WorkerThe GCC and Clang linkers allow one to first sort matched symbols for each
702*61c4878aSAndroid Build Coastguard Workerwildcard pattern by alignment with the ``SORT_BY_ALIGNMENT`` keyword, which can
703*61c4878aSAndroid Build Coastguard Workerreduce the amount of necessary padding bytes and save memory. This can be used
704*61c4878aSAndroid Build Coastguard Workerto enable alignment sort on a per-pattern basis like so:
705*61c4878aSAndroid Build Coastguard Worker
706*61c4878aSAndroid Build Coastguard Worker.. code-block:: text
707*61c4878aSAndroid Build Coastguard Worker
708*61c4878aSAndroid Build Coastguard Worker   .text : { *(SORT_BY_ALIGNMENT(.init*)) *(SORT_BY_ALIGNMENT(.text*)) }
709*61c4878aSAndroid Build Coastguard Worker
710*61c4878aSAndroid Build Coastguard WorkerThis keyword can be applied globally to all wildcard matches in your linker
711*61c4878aSAndroid Build Coastguard Workerscript by passing the ``--sort-section=alignment`` option to the linker.
712*61c4878aSAndroid Build Coastguard Worker
713*61c4878aSAndroid Build Coastguard WorkerSee the `ld manual <https://sourceware.org/binutils/docs/ld/Input-Section-Wildcards.html>`_
714*61c4878aSAndroid Build Coastguard Workerfor more information.
715