/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include // FOLLY_KEEP // // When applied to a function, prevents removal of the function. Useful for // marking functions which it is desirable to keep. // // A common use-case is for keeping unused functions in test or benchmark // programs which serve as convenient targets for inspecting how the compiler // translates source code to machine code. Such functions may be disassembled // for inspection in the debugger of with the objdump tool, and are often, for // lack of imagination, called check functions in test and benchmark programs. // // Example: // // extern "C" FOLLY_KEEP void check_throw_int_0() { // throw 0; // } // // $ objdump -dCM intel-mnemonic path/to/binary | less // # less permits searching for check_throw_int_0 // // $ gdb path/to/binary -q -batch -ex 'disassemble check_throw_int_0' // // Functions may be removed when building with both function-sections and // gc-sections. It is tricky to keep them; this utility captures the steps // required. // // In order for this mechanism to work, this header must be included. This // mechanism relies on the hidden global variable below. // // The linker, when asked to with --gc-sections, may throw out unreferenced // sections. When the compiler emits each function into its own section, as it // does when asked to with -ffunction-sections, the linker will throw out // unreferenced functions. The key is to move all kept functions into a single // section, avoiding the behavior of -ffunction-sections, and then force the // compiler to emit some reference to at least one function in that section. // This way, the linker will see at least one reference to the kept section, // and so will not throw it out. #if __GNUC__ && __linux__ #define FOLLY_KEEP [[gnu::section(".text.folly.keep")]] #else #define FOLLY_KEEP #endif #if __GNUC__ && __linux__ #if defined(__clang__) || FOLLY_ARM || FOLLY_AARCH64 #define FOLLY_KEEP_DETAIL_ATTR_NAKED [[gnu::naked]] #else #define FOLLY_KEEP_DETAIL_ATTR_NAKED #endif #define FOLLY_KEEP_DETAIL_ATTR_NOINLINE [[gnu::noinline]] #else #define FOLLY_KEEP_DETAIL_ATTR_NAKED #define FOLLY_KEEP_DETAIL_ATTR_NOINLINE #endif namespace folly { namespace detail { // marking this as [[gnu::naked]] gets clang not to emit any text for this FOLLY_KEEP FOLLY_KEEP_DETAIL_ATTR_NAKED static void keep_anchor() {} class keep { public: // must accept the anchor function as an argument FOLLY_KEEP_DETAIL_ATTR_NOINLINE explicit keep(void (*)()) noexcept {} }; // noinline ctor and trivial dtor minimize the text size of this static keep keep_instance{keep_anchor}; // weak and noinline to prevent the compiler from eliding calls template FOLLY_ATTR_WEAK FOLLY_NOINLINE void keep_sink(T&&...) {} template FOLLY_ATTR_WEAK FOLLY_NOINLINE void keep_sink_nx(T&&...) noexcept {} } // namespace detail } // namespace folly