|
|
@@ -99,11 +99,36 @@ The ``demo_profiling`` example demonstrates:
|
|
|
|
|
|
You can find the example at ``application/baremetal/demo_profiling`` in the Nuclei SDK.
|
|
|
|
|
|
+## Key Reminders
|
|
|
+
|
|
|
+> [!IMPORTANT]
|
|
|
+> **Apply profiling/coverage flags only to the application being analyzed.**
|
|
|
+> Do not enable `-pg` or `-coverage` globally for the whole SDK or unrelated components. These options should be added only to the source files or directories of the target application; otherwise they can introduce unexpected build, link, runtime, or memory issues.
|
|
|
+
|
|
|
+> [!IMPORTANT]
|
|
|
+> **Profiling and coverage need a large heap.**
|
|
|
+> Both gprof and gcov may allocate a significant amount of runtime memory, especially coverage collection. Make sure your heap is large enough before enabling these features.
|
|
|
+>
|
|
|
+> The `demo_profiling` example is intended to run with `DOWNLOAD=sram` or `DOWNLOAD=ddr` so that more runtime memory is available for profiling experiments.
|
|
|
+> In the linker script, `__HEAP_SIZE` only defines the minimum reserved heap space. The actual heap available to `malloc` is bounded by `__heap_start` and `__heap_end`, so it also depends on the final linker layout and remaining free RAM.
|
|
|
+> To reduce integration issues, it is recommended to use a memory layout with enough free RAM and verify the effective heap size in your own project.
|
|
|
+
|
|
|
+> [!TIP]
|
|
|
+> **This profiling component can be reused independently.**
|
|
|
+> You can copy the profiling library sources into another project and integrate them without moving the whole example application. A practical reference is the Nuclei Studio IDE flow below: add the required profiling sources, configure the library, then enable profiling or coverage compiler flags only for the application code you want to analyze.
|
|
|
+
|
|
|
## How to Use
|
|
|
|
|
|
### Step 1: Add Profiling Component to Your Project
|
|
|
|
|
|
-Add this `profiling` folder into your project or create project based on ``demo_profiling`` example, then configure your build system:
|
|
|
+Add this `profiling` folder into your project or create project based on ``demo_profiling`` example, then configure your build system.
|
|
|
+
|
|
|
+This component is designed to be integrated as a reusable library:
|
|
|
+
|
|
|
+- Add the required profiling sources and headers into your project
|
|
|
+- Configure the profiling library as needed for your platform
|
|
|
+- Enable `-pg` or `-coverage` only on the application source files you want to analyze
|
|
|
+- Do not apply these options globally to the whole SDK or all middleware
|
|
|
|
|
|
#### For Nuclei Studio IDE
|
|
|
|
|
|
@@ -113,7 +138,8 @@ Add this `profiling` folder into your project or create project based on ``demo_
|
|
|
4. Add the following flags:
|
|
|
- `-pg` for profiling
|
|
|
- `-coverage` for coverage analysis
|
|
|
-5. Click **Apply and Close**, then rebuild your project
|
|
|
+5. Apply the flags only to the selected application source file or source folder that needs profiling/coverage
|
|
|
+6. Click **Apply and Close**, then rebuild your project
|
|
|
|
|
|

|
|
|
|
|
|
@@ -153,6 +179,8 @@ include $(NUCLEI_SDK_ROOT)/Build/Makefile.base
|
|
|
> - Profiling and coverage analysis require significant memory
|
|
|
> - Use ``DOWNLOAD=sram`` or ``DOWNLOAD=ddr`` for sufficient runtime memory
|
|
|
> - When using ``-coverage`` flag, heap space may be insufficient - consider ``DOWNLOAD=ddr``
|
|
|
+> - Increase heap size explicitly if your application or test case uses gcov/gprof buffers heavily
|
|
|
+> - Avoid `DOWNLOAD=ilm` for such examples unless you have verified the available memory is still sufficient
|
|
|
>
|
|
|
> **Optimization Considerations:**
|
|
|
> - Use ``-O0`` optimization level for accurate profiling results
|
|
|
@@ -161,6 +189,10 @@ include $(NUCLEI_SDK_ROOT)/Build/Makefile.base
|
|
|
> **Extension Compatibility:**
|
|
|
> - When using Zc extension with ``-pg``, note that ``-fomit-frame-pointer`` (enabled by Zc) is incompatible with ``-pg``
|
|
|
> - You may need to adjust compiler flags accordingly
|
|
|
+>
|
|
|
+> **Scope of Instrumentation:**
|
|
|
+> - Set `APPDIRS` or equivalent build rules so that `-pg` and `-coverage` are added only to the target application sources
|
|
|
+> - Do not enable these flags for the whole SDK by default
|
|
|
|
|
|
### Step 2: Customize gprof_stub.c (For Profiling Only)
|
|
|
|
|
|
@@ -295,3 +327,78 @@ llvm-cov gcov *.gcda
|
|
|
> - ``.gcda`` files: Runtime coverage data generated by your program execution (different format for GCC vs LLVM/Clang)
|
|
|
> - ``.gcov`` files: Annotated source files generated by gcov tools showing line-by-line coverage
|
|
|
> - GCC and LLVM/Clang generate incompatible ``.gcda`` formats - use the corresponding toolchain's gcov tool
|
|
|
+
|
|
|
+## FAQ
|
|
|
+
|
|
|
+### Why do I see garbled coverage or profiling dump output, or partial dump logs?
|
|
|
+
|
|
|
+In most cases, this means the runtime memory is insufficient, especially heap space used by gcov or gprof internal buffers.
|
|
|
+
|
|
|
+Typical symptoms include:
|
|
|
+
|
|
|
+- Dump output looks truncated, corrupted, or mixed with unexpected text
|
|
|
+- Coverage dump starts but does not complete correctly
|
|
|
+- Runtime errors disappear after increasing heap size
|
|
|
+
|
|
|
+Check the following first:
|
|
|
+
|
|
|
+- Make sure the application has enough heap, not only enough stack
|
|
|
+- Verify the actual available SRAM size in your project
|
|
|
+- Compare your linker script and `_sbrk` implementation with the SDK example, because the effective heap size may not match the number you expected from a macro or comment
|
|
|
+
|
|
|
+The `demo_profiling` example is typically run with `DOWNLOAD=sram` or `DOWNLOAD=ddr` so that more runtime memory is available for profiling experiments.
|
|
|
+The SDK linker script only guarantees a minimum heap reservation through `__HEAP_SIZE`. The actual heap that `malloc` can use is the range between `__heap_start` and `__heap_end`, so the effective size also depends on the linker layout, stack placement, and remaining RAM in your project.
|
|
|
+
|
|
|
+### Why are `gmon.out` or `*.gcda` files not generated when I use console or UART output?
|
|
|
+
|
|
|
+If you use `gprof_collect(2)` or `gcov_collect(2)`, the data is dumped to console output instead of being written directly to host files.
|
|
|
+
|
|
|
+That means:
|
|
|
+
|
|
|
+- UART or console output alone does not create `gmon.out` or `*.gcda` files automatically
|
|
|
+- You must save the dump log first
|
|
|
+- Then run `parse.py` on the host to reconstruct the binary profiling or coverage files
|
|
|
+
|
|
|
+Example:
|
|
|
+
|
|
|
+```bash
|
|
|
+python3 /path/to/Components/profiling/parse.py prof.log
|
|
|
+```
|
|
|
+
|
|
|
+If you want the files to be written directly to the host filesystem, use interface `1` with semihosting enabled instead.
|
|
|
+
|
|
|
+### What does `_mcleanup: tos overflow` usually mean?
|
|
|
+
|
|
|
+This error typically indicates a profiling configuration problem, and the first items to check are:
|
|
|
+
|
|
|
+- Heap is still too small for profiling runtime allocation
|
|
|
+- `-pg` or `-coverage` was applied to the wrong scope
|
|
|
+- Too much code was instrumented instead of only the target application
|
|
|
+
|
|
|
+In practice, insufficient heap is a very common cause. If increasing heap resolves earlier dump failures but triggers `_mcleanup: tos overflow`, review both memory size and instrumentation scope together.
|
|
|
+
|
|
|
+### Should I add `-pg` and `-coverage` to the whole SDK or all source files?
|
|
|
+
|
|
|
+No. These flags should only be added to the application code you want to analyze.
|
|
|
+
|
|
|
+Do not enable them globally for:
|
|
|
+
|
|
|
+- The whole SDK
|
|
|
+- All middleware
|
|
|
+- All BSP or driver code
|
|
|
+- Unrelated libraries
|
|
|
+
|
|
|
+Instrumenting too much code increases memory usage and may introduce unexpected profiling behavior. In IDE projects, apply the flags only to the target source file or source folder. In Makefile projects, restrict the flags through `APPDIRS` or equivalent per-application build rules.
|
|
|
+
|
|
|
+### I already configured heap to 2 KB, 20 KB, or 40 KB. Why can it still fail?
|
|
|
+
|
|
|
+Because the configured heap number alone is not enough evidence that the runtime can actually allocate that much memory.
|
|
|
+
|
|
|
+Please verify:
|
|
|
+
|
|
|
+- The linker script really leaves enough heap region at runtime
|
|
|
+- `_sbrk` is implemented correctly
|
|
|
+- Stack, heap, and other runtime sections are not overlapping
|
|
|
+- Your SDK port uses the same memory layout assumptions as the Nuclei SDK example
|
|
|
+
|
|
|
+In one real integration case, profiling still failed at 40 KB heap and started working only after increasing heap to 80 KB. If the usage flow is otherwise correct, treat allocation failure as the first debugging direction.
|