Clang based code coverage tool enabling on edk2 - shijunjing/edk2 GitHub Wiki
Useful link: http://logan.tw/posts/2015/04/28/check-code-coverage-with-clang-and-lcov/
To implement these GCOV run-time instrumentation API, you need understand the .gcno and .gcda file formats. For the .gcno and .gcda file formats, see below links. https://gcc.gnu.org/onlinedocs/gcc/Gcov-Data-Files.html
Try to enable a compiler instrumentation based code coverage tool for edk2 DXE phase Target usage demo:
~/wksp_efi/edk2-fork$ git checkout clang_code_coverage
~/wksp_efi/edk2-fork$ build -t CLANGCOV38 -p OvmfPkg/OvmfPkgIa32X64.dsc -a IA32 -a X64 -b NOOPT -m MdeModulePkg/Application/HelloWorld/HelloWorld.inf
~/wksp_efi/edk2-fork$ build -t CLANG38 -p OvmfPkg/OvmfPkgIa32X64.dsc -a IA32 -a X64 -b NOOPT
~/wksp_efi/edk2-fork$ cd Build/rootfs/
~/wksp_efi/edk2-fork/Build/rootfs$ cp ../Ovmf3264/NOOPT_CLANGCOV38/X64/HelloWorld.efi .
~/wksp_efi/edk2-fork/Build/rootfs$ qemu-system-x86_64 -nographic -global isa-debugcon.iobase=0x402 -debugcon file:serial.log -pflash ../Ovmf3264/NOOPT_CLANG38/FV/OVMF.fd -hda fat:. -net none
Then, boot into shell and run HelloWorld.efi as below
FS0:\> HelloWorld.efi
GcdaCovLibConstructor begin
GcdaCovLibConstructor: preinit function pointers size = 0x0000000000000000
GcdaCovLibConstructor: init function pointers size = 0x000000000000005D
llvm_gcda_summary_info is called,fn address =0x0000000005FBD610
llvm_gcda_emit_arcs is called,fn address =0x0000000005FBD660
llvm_gcda_emit_function is called,fn address =0x0000000005FBD6B0
llvm_gcda_start_file is called,fn address =0x0000000005FBD710
llvm_gcda_end_file is called,fn address =0x0000000005FBD760
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
llvm_gcov_init is called, wfn= 0x0000000005FC9D50 and ffn= 0x0000000000000000
GcdaCovLibConstructor: ctors function pointers size = 0x0000000000000000
GcdaCovLibConstructor done
UEFI Hello World!
GcdaCovLibDestructor begin
GcdaCovLibDestructor: fini function pointers size = 0x0000000000000000
llvm_writeout_files is called,curr->fn =0x0000000005FC9D50
system hang!!!
or directly build all modules:
jshi19@ub2-uefi-b01:~/wksp_efi/edk2-fork$ build -t CLANGCOV38 -p OvmfPkg/OvmfPkgIa32X64.dsc -a IA32 -a X64 -b NOOPT
currently, finish the clang Gcov/Lcov profile instrumentation in build and blank instrumentation Libs. Need to debug the Uefi version instrumentation API Libs (e.g. __llvm_gcov_init, llvm_gcda_emit_function, etc.). These APIs are defined in D:\Project\LLVM\llvm\projects\compiler-rt\lib\profile\GCDAProfiling.c.
The show stopper issue is the below code invoke the llvm_gcov_init(fn_ptr wfn, fn_ptr ffn), but the passed in wfn and ffn functions pointer values are not correct, see above HelloWorld run hang. Don't know what's wrong and why the instrumented __llvm_gcov_init cannot pass in correct wfn and ffn.
for (int i = 0; i < size; i++){
(*__init_array_start [i]) (0, 0, 0);
}
- 20190307
Above system hang caused by instrumented HelloWorld.efi is because the X64 PLT relocations are not corrected coverted by GenFW:
jshi19@ub2-uefi-b01:~/wksp_efi/edk2-fork$ readelf /home/jshi19/wksp_efi/edk2-fork/Build/Ovmf3264/NOOPT_CLANGCOV38/X64/MdeModulePkg/Application/HelloWorld/HelloWorld/DEBUG/HelloWorld.dll -r
Relocation section '.rela.text' at offset 0x71a08 contains 13798 entries:
Offset Info Type Sym. Value Sym. Name + Addend
00000000025d 000200000002 R_X86_64_PC32 000000000003a780 .data + 1ac
00000000027c 006100000004 R_X86_64_PLT32 000000000002eb20 llvm_gcda_start_file - 4
0000000002e0 005400000004 R_X86_64_PLT32 000000000002eac0 llvm_gcda_emit_functio - 4
0000000002ff 006500000004 R_X86_64_PLT32 000000000002ea70 llvm_gcda_emit_arcs - 4
00000000031b 007a00000004 R_X86_64_PLT32 000000000002ea20 llvm_gcda_summary_info - 4
000000000320 009000000004 R_X86_64_PLT32 000000000002eb70 llvm_gcda_end_file - 4
000000000342 000100000004 R_X86_64_PLT32 0000000000000240 .text - 4
000000000349 000200000002 R_X86_64_PC32 000000000003a780 .data + 84d8
... ...
Current ELF PLT32 is converted in edk2\BaseTools\Source\C\GenFw\Elf64Convert.c:
case R_X86_64_PLT32:
//
// Treat R_X86_64_PLT32 relocations as R_X86_64_PC32: this is
// possible since we know all code symbol references resolve to
// definitions in the same module (UEFI has no shared libraries),
// and so there is never a reason to jump via a PLT entry,
// allowing us to resolve the reference using the symbol directly.
//
VerboseMsg ("Treating R_X86_64_PLT32 as R_X86_64_PC32 ...");
/* fall through */
case R_X86_64_PC32:
... ...
So the PLT32 relocation entries are not mapped to PLT at all!
So, currently only IA32 clang build can support the clang coverage instrumentation:
jshi19@ub2-uefi-b01:~/wksp_efi/edk2-fork$ build -t CLANGCOV38 -p OvmfPkg/OvmfPkgIa32.dsc -a IA32 -b NOOPT -m MdeModulePkg/Application/HelloWorld/HelloWorld.inf
"/home/jshi19/llvm/releaseinstall/bin/clang" -o /home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdeModulePkg/Application/HelloWorld/HelloWorld/DEBUG/HelloWorld.dll -nostdlib -Wl,-n,-q,--gc-sections -z common-page-size=0x40 -Wl,--entry,_ModuleEntryPoint -u _ModuleEntryPoint -Wl,-Map,/home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdeModulePkg/Application/HelloWorld/HelloWorld/DEBUG/HelloWorld.map,--whole-archive -Wl,-O0 -Wl,-melf_i386 -Wl,--oformat=elf32-i386 -Wl,--start-group,@/home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdeModulePkg/Application/HelloWorld/HelloWorld/OUTPUT/static_library_files.lst,--end-group -g -fshort-wchar -fno-builtin -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -ffunction-sections -fdata-sections -include AutoGen.h -fno-common -DSTRING_ARRAY_NAME=HelloWorldStrings -Wno-parentheses-equality -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-empty-body -Wno-unused-const-variable -Wno-varargs -Wno-unknown-warning-option -fno-stack-protector -mms-bitfields -Wno-address -Wno-shift-negative-value -Wno-unknown-pragmas -Wno-incompatible-library-redeclaration -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -msoft-float -mno-implicit-float -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang -funsigned-char -fno-ms-extensions -Wno-null-dereference -m32 -O0 -march=i586 -target i686-pc-linux-gnu -g -mno-mmx -mno-sse -D DISABLE_NEW_DEPRECATED_INTERFACES -Wl,--defsym=PECOFF_HEADER_SIZE=0x220 -Wl,--script=/home/jshi19/wksp_efi/edk2-fork/BaseTools/Scripts/GccBase.lds -Wno-error -O0
/usr/bin/ld: warning: section `.data' type changed to PROGBITS
/home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdePkg/Library/BaseLib/BaseLib/OUTPUT/BaseLib.lib(CheckSum.obj): In function `CalculateSum8':
/home/jshi19/wksp_efi/edk2-fork/MdePkg/Library/BaseLib/CheckSum.c:288: undefined reference to `llvm_gcda_start_file'
/home/jshi19/wksp_efi/edk2-fork/MdePkg/Library/BaseLib/CheckSum.c:(.text.__llvm_gcov_writeout+0x9d): undefined reference to `llvm_gcda_emit_function'
/home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdePkg/Library/BaseLib/BaseLib/OUTPUT/BaseLib.lib(CheckSum.obj): In function `CalculateCrc32':
/home/jshi19/wksp_efi/edk2-fork/MdePkg/Library/BaseLib/CheckSum.c:288: undefined reference to `llvm_gcda_emit_arcs'
/home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdePkg/Library/BaseLib/BaseLib/OUTPUT/BaseLib.lib(CheckSum.obj): In function `CalculateSum32':
/home/jshi19/wksp_efi/edk2-fork/MdePkg/Library/BaseLib/CheckSum.c:289: undefined reference to `llvm_gcda_summary_info'
/home/jshi19/wksp_efi/edk2-fork/MdePkg/Library/BaseLib/CheckSum.c:(.text.__llvm_gcov_writeout+0xd9): undefined reference to `llvm_gcda_end_file'
/home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdePkg/Library/BaseLib/BaseLib/OUTPUT/BaseLib.lib(CheckSum.obj): In function `__llvm_gcov_init':
CheckSum.c:(.text.__llvm_gcov_init+0x17): undefined reference to `llvm_gcov_init'
/home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdePkg/Library/BaseLib/BaseLib/OUTPUT/BaseLib.lib(SwitchStack.obj): In function `__llvm_gcov_writeout':
SwitchStack.c:(.text.__llvm_gcov_writeout+0x3c): undefined reference to `llvm_gcda_start_file'
SwitchStack.c:(.text.__llvm_gcov_writeout+0x9d): undefined reference to `llvm_gcda_emit_function'
SwitchStack.c:(.text.__llvm_gcov_writeout+0xb8): undefined reference to `llvm_gcda_emit_arcs'
SwitchStack.c:(.text.__llvm_gcov_writeout+0xd4): undefined reference to `llvm_gcda_summary_info'
SwitchStack.c:(.text.__llvm_gcov_writeout+0xd9): undefined reference to `llvm_gcda_end_file'
/home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdePkg/Library/BaseLib/BaseLib/OUTPUT/BaseLib.lib(SwitchStack.obj): In function `__llvm_gcov_init':
SwitchStack.c:(.text.__llvm_gcov_init+0x17): undefined reference to `llvm_gcov_init'
/home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdePkg/Library/BaseLib/BaseLib/OUTPUT/BaseLib.lib(SwapBytes64.obj): In function `__llvm_gcov_writeout':
SwapBytes64.c:(.text.__llvm_gcov_writeout+0x3c): undefined reference to `llvm_gcda_start_file'
SwapBytes64.c:(.text.__llvm_gcov_writeout+0x9d): undefined reference to `llvm_gcda_emit_function'
SwapBytes64.c:(.text.__llvm_gcov_writeout+0xb8): undefined reference to `llvm_gcda_emit_arcs'
SwapBytes64.c:(.text.__llvm_gcov_writeout+0xd4): undefined reference to `llvm_gcda_summary_info'
SwapBytes64.c:(.text.__llvm_gcov_writeout+0xd9): undefined reference to `llvm_gcda_end_file'
/home/jshi19/wksp_efi/edk2-fork/Build/OvmfIa32/NOOPT_CLANGCOV38/IA32/MdePkg/Library/BaseLib/BaseLib/OUTPUT/BaseLib.lib(SwapBytes64.obj): In function `__llvm_gcov_init':
... ...
- 20190316
OK! Now it looks correct.
jshi19@ub2-uefi-b01:~/wksp_efi/edk2-fork$ git checkout clang_code_coverage
jshi19@ub2-uefi-b01:~/wksp_efi/edk2-fork$ build -t CLANG38 -p OvmfPkg/OvmfPkgIa32.dsc -a IA32 -b NOOPT
jshi19@ub2-uefi-b01:~/wksp_efi/edk2-fork$ build -t CLANGCOV38 -p OvmfPkg/OvmfPkgIa32.dsc -a IA32 -b NOOPT -m MdeModulePkg/Application/HelloWorld/HelloWorld.inf
jshi19@ub2-uefi-b01:~/wksp_efi/edk2-fork$ cd Build/rootfs/
jshi19@ub2-uefi-b01:~/wksp_efi/edk2-fork/Build/rootfs$ cp ../OvmfIa32/NOOPT_CLANGCOV38/IA32/HelloWorld.efi .
jshi19@ub2-uefi-b01:~/wksp_efi/edk2-fork/Build/rootfs$ qemu-system-x86_64 -nographic -global isa-debugcon.iobase=0x402 -debugcon file:serial.log -pflash ../OvmfIa32/NOOPT_CLANG38/FV/OVMF.fd -hda fat:. -net none
Shell> fs0:
FS0:\> HelloWorld.efi
GcdaCovLibConstructor begin
GcdaCovLibConstructor: preinit function pointers size = 0x0000000000000000
GcdaCovLibConstructor: init function pointers size = 0x000000000000005C
llvm_gcda_summary_info is called,fn address =0x0000000005F81BA0
llvm_gcda_emit_arcs is called,fn address =0x0000000005F81BF0
llvm_gcda_emit_function is called,fn address =0x0000000005F81C50
llvm_gcda_start_file is called,fn address =0x0000000005F81CC0
llvm_gcda_end_file is called,fn address =0x0000000005F81D20
llvm_gcov_init is called, wfn= 0x0000000005F2E240 and ffn= 0x0000000005F2E6A0
llvm_gcov_init is called, wfn= 0x0000000005F2F430 and ffn= 0x0000000005F2F4E0
llvm_gcov_init is called, wfn= 0x0000000005F2F780 and ffn= 0x0000000005F2F830
... ...
llvm_gcov_init is called, wfn= 0x0000000005F827B0 and ffn= 0x0000000005F82860
llvm_gcov_init is called, wfn= 0x0000000005F83ED0 and ffn= 0x0000000005F84140
GcdaCovLibConstructor: ctors function pointers size = 0x0000000000000000
GcdaCovLibConstructor done
UEFI Hello World!
GcdaCovLibDestructor begin
GcdaCovLibDestructor: fini function pointers size = 0x0000000000000000
llvm_writeout_files is called,curr->fn =0x0000000005F2E240
llvm_gcda_start_file is called,fn address =0x0000000005F81CC0
llvm_gcda_emit_function is called,fn address =0x0000000005F81C50
llvm_gcda_emit_arcs is called,fn address =0x0000000005F81BF0
llvm_gcda_emit_function is called,fn address =0x0000000005F81C50
llvm_gcda_emit_arcs is called,fn address =0x0000000005F81BF0
... ...
Be working on porting the D:\Project\LLVM\compiler-rt\lib\profile\GCDAProfiling.c gcov profiling runtime call back routines to \home\jshi19\wksp_efi\edk2-fork\MdeModulePkg\Library\GcdaCovLib\GcdaCovLib.c
These call back routines instrumentation are implemented in llvm\lib\Transforms\Instrumentation\GCOVProfiling.cpp
Some example to understand how clang gcov works:
jshi19@ub2-uefi-b01:~/llvm/wrongcode/coverage$ cat readme.txt
http://logan.tw/posts/2015/04/28/check-code-coverage-with-clang-and-lcov/
https://github.com/shijunjing/edk2/wiki/Clang-based-code-coverage-tool-enabling-on-edk2
clang -fprofile-arcs -ftest-coverage main.c
./a.out
llvm-cov gcov -f -b main.gcda
lcov --directory . --base-directory . --gcov-tool ~/llvm/wrongcode/coverage/llvm-gcov.sh --capture -o cov.info
genhtml cov.info -o output