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