1. Background
In the performance optimization practice of C/C++, PGO (Profile-Guided Optimization) is a very effective compilation optimization technique. The basic process is divided into two stages:
-
Generation Stage (profile-generate): The compiler inserts additional counting logic into the code (e.g., function call counts, branch hit counts, etc.).
-
Usage Stage (profile-use): The runtime collected profile data is fed back to the compiler to guide optimization decisions (function inlining, branch prediction, code layout, etc.).
Theoretically, this process should be transparent to developers, but on the Kirin V10 SP2 (the default compiler for gcc 7.3.0), PGO may encounter an error indicating missing gcov symbols, preventing successful compilation/linking.
2. Problem Phenomenon
The compilation succeeds in the profile-generate stage, but during the runtime stage, an error similar to the following occurs:
undefined reference to `__gcov_indirect_call_counter’
Even when explicitly specifying -lgcov, the problem remains unresolved. Using nm libgcov.a confirms that the __gcov_indirect_call_counter symbol indeed exists, but the final generated executable still shows the symbol status as U (undefined).
3. Problem Cause
There is a certain issue in the implementation of PGO/-fprofile-generate in the GCC 7.x series:
-
Under -fprofile-generate, the compiler inserts symbols related to indirect call profiling, such as __gcov_indirect_call_counter. As expected, these symbol definitions should come from libgcov.a and be automatically pulled in by the linker. However, in the implementation of GCC 7.3.0, some object files were not correctly resolved into the final link result, and even explicitly writing -lgcov does not take effect.
This leads to the situation of “symbol exists → linker did not pull it in → final binary is missing”.
4. Solution: Force the Entire libgcov to Link
The key point is: do not rely solely on the linker to resolve on demand, but rather force the entire libgcov.a library into the final executable. Under the GNU ld or gold linker, the –whole-archive parameter can be used:
g++ -o myprog myprog.o -Wl,–whole-archive /usr/lib/gcc/x86_64-linux-gnu/7.3.0/libgcov.a -Wl,–no-whole-archive
In this way, all object files in libgcov.a will be packaged into the final binary, ensuring that symbols like __gcov_indirect_call_counter are correctly defined.
5. Summary
-
Phenomenon: Missing __gcov_indirect_call_counter symbol during the PGO stage, even specifying -lgcov is ineffective.
-
Cause: The gcov symbols inserted by GCC 7.3.0 under profile-generate were not properly resolved into the final executable.
-
Solution: Use the –whole-archive parameter to force the entire libgcov.a to link, ensuring symbol integrity.
This issue no longer occurs in GCC 8.x and later versions. It is recommended to keep an eye on software updates for the operating system distribution. If subsequent revisions or upgrade packages for GCC are provided, it is advisable to update to the latest stable version supported by the distribution for better PGO support.
📬 Welcome to follow the WeChat public account “Hankin-Liu’s Technical Research Room” for mentorship and knowledge sharing. Continuously sharing valuable technical content related to innovation, software performance testing, optimization, programming skills, and software debugging techniques.