-fprofile-instr-generate -fcoverage-mapping no longer outputting __llvm_profile_init on bare-metal targets

We have been migrating our bare-metal implementation/hack of a code-coverage runtime to LLVM 18.0 and have noticed that for our target arm-none-eabi and aarch64-none-elf the .init_array entry for __llvm_profile_init and __llvm_profile_register_names_function are no longer being generated.

I understand that these should only be generated on certain targets/platforms where it is not guaranteed that there will be a compiler-rt runtime available and linker defined symbols to find the bounds of the counter sections. However I would expect that the bare-metal platforms to be good candidates for that.

I think I’ve tracked down the change to [NFC][InstrProf] Refactor InstrProfiling lowering pass by mtrofin · Pull Request #74970 · llvm/llvm-project · GitHub [NFC][InstrProf] Refactor InstrProfiling lowering pass

It looks like the pass that would insert the __llvm_profile_init isn’t added if Clang instrumentation -fprofile-instr-generate is used.

Is this likely to be intended behaviour? I can raise a GitHub issue otherwise.

I’m confident I’ll be able to rewrite our runtime to use linker defined symbols and insert the .init_array manually but there’s always the possibility that someone else might not be able to.

I think this is due to [InstrProfiling] No runtime registration for ELF, COFF, Mach-O and XCOFF by petrhosek · Pull Request #77225 · llvm/llvm-project · GitHub. That change was motivated by our experience from using -fprofile-instr-generate on baremetal targets and I think it’s desirable but I should have announced it more broadly. If this becomes an issue for someone, we could consider introducing a backend option to force the use of runtime registration, but I don’t think we should do it automatically based on the OS as we did prior to that change.

Thanks for letting us know. Good to know that the change was intentional, I’ll adapt our runtime.