Uploaded image for project: 'Embedded Software & Tools'
  1. Embedded Software & Tools
  2. EXT_EP-12179

Code coverage breaks naked functions

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Medium Medium
    • Code Generation Tools
    • CODEGEN-13041
    • Hide
      ARMCLANG_4.0.0.LTS
      ARMCLANG_3.2.0.LTS
      Show
      ARMCLANG_4.0.0.LTS ARMCLANG_3.2.0.LTS
    • Hide
      ARMCLANG_3.2.4.LTS*
      ARMCLANG_4.0.2.LTS*
      Show
      ARMCLANG_3.2.4.LTS* ARMCLANG_4.0.2.LTS*
    • default

      Observation
      Enabling code coverage for a file that contains naked function breaks the naked function.

      More details
      The function we observe break is implemented as follows:

      cpu.c
      void _attribute_((naked)) CPUDelay(uint32_t count)

      { // Loop the specified number of times. // The naked attribute tells the compiler that the function is effectively // hand-coded assembly implemented using inlined assembly without operands. // As such, it assumes that the C calling conventions are obeyed, and we can // assume count is in R0. __asm volatile("CPUdel%=:\n" " subs r0, #1\n" " bne CPUdel%=\n" " bx lr\n" : /* No output */ : /* No input */ : "r0", "cc" /* Clobbers. "cc" is the flags */ ); }

      As per the documentation of a naked function, it assumes the first argument of the function is in R0. In the failing code, CPUDelay(3) is called.

      Code coverage disabled (code functional)
      Call site:

      Call site
      0x000004F8 2003 movs r0, #3
      0x000004FA F001F97B bl CPUDelay
      CPUDelay():

      CPUDelay()
      0x000017F4 3801 subs r0, #1
      0x000017F6 D1FD bne CPUDelay
      0x000017F8 4770 bx r14
      Code coverage enabled (failing)
      Call site:

      Call site
      0x0000043E 2003 movs r0, #3
      __llvm_coverage_mapping
      0x00000440 F001FBDC bl CPUDelay
      CPUDelay():

      CPUDelay()

      1. Highlighted section: Start
        0x00001BFC 4905 ldr r1, pc, #0x14
        0x00001BFE 6848 ldr r0, r1, #4
        0x00001C00 680A ldr r2, [r1]
        0x00001C02 2300 movs r3, #0
        0x00001C04 1C52 adds r2, r2, #1
        0x00001C06 4158 adcs r0, r3
        0x00001C08 600A str r2, [r1]
        0x00001C0A 6048 str r0, r1, #4
      2. Highlighted section: End
        0x00001C0C 3801 subs r0, #1
        0x00001C0E D1FD bne #0x1c0c
        0x00001C10 4770 bx r14
        The highlighted code is added by the code coverage. R0 is observed to be 0 after those instructions are executed. The subsequent "substract 1 from 0" is problematic.

      Workaround
      In our case, we could work around it by disabling code coverage for the entire cpu.c file (it only contains naked functions). For others, that may not be an acceptable workaround.

      Update: Adding attribute no_instrument_function will also fix the issue.

      void _attribute_((naked, no_profile_instrument_function)) CPUDelay(uint32_t count)

      { // ... }

      Suggested Solutions
      Ensure the code coverage code does not break the "naked" function promise.
      Do not support code coverage for naked functions

            syncuser TI User
            syncuser TI User
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: