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
  ... ...

20190607

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
⚠️ **GitHub.com Fallback** ⚠️