Skip to content

Commit be00a61

Browse files
committed
doc: update profiling integration guidance and FAQ
Document the profiling and coverage integration constraints that are easy to miss when users reuse the profiling component outside the demo application. Update Components/profiling/README.md with key reminders about limiting -pg/-coverage to target application sources, checking heap and linker layout, reusing the profiling component independently, and parsing console dump output with parse.py. Also add FAQ entries for common failure cases such as corrupted dump output, missing generated files, and _mcleanup: tos overflow, update app.rst with the same guidance for demo_profiling, and record the documentation enhancement in the changelog. Signed-off-by: Huaqi Fang <578567190@qq.com>
1 parent 78c5d17 commit be00a61

3 files changed

Lines changed: 128 additions & 2 deletions

File tree

Components/profiling/README.md

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,36 @@ The ``demo_profiling`` example demonstrates:
9999
100100
You can find the example at ``application/baremetal/demo_profiling`` in the Nuclei SDK.
101101
102+
## Key Reminders
103+
104+
> [!IMPORTANT]
105+
> **Apply profiling/coverage flags only to the application being analyzed.**
106+
> 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.
107+
108+
> [!IMPORTANT]
109+
> **Profiling and coverage need a large heap.**
110+
> 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.
111+
>
112+
> The `demo_profiling` example is intended to run with `DOWNLOAD=sram` or `DOWNLOAD=ddr` so that more runtime memory is available for profiling experiments.
113+
> 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.
114+
> 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.
115+
116+
> [!TIP]
117+
> **This profiling component can be reused independently.**
118+
> 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.
119+
102120
## How to Use
103121
104122
### Step 1: Add Profiling Component to Your Project
105123
106-
Add this `profiling` folder into your project or create project based on ``demo_profiling`` example, then configure your build system:
124+
Add this `profiling` folder into your project or create project based on ``demo_profiling`` example, then configure your build system.
125+
126+
This component is designed to be integrated as a reusable library:
127+
128+
- Add the required profiling sources and headers into your project
129+
- Configure the profiling library as needed for your platform
130+
- Enable `-pg` or `-coverage` only on the application source files you want to analyze
131+
- Do not apply these options globally to the whole SDK or all middleware
107132
108133
#### For Nuclei Studio IDE
109134
@@ -113,7 +138,8 @@ Add this `profiling` folder into your project or create project based on ``demo_
113138
4. Add the following flags:
114139
- `-pg` for profiling
115140
- `-coverage` for coverage analysis
116-
5. Click **Apply and Close**, then rebuild your project
141+
5. Apply the flags only to the selected application source file or source folder that needs profiling/coverage
142+
6. Click **Apply and Close**, then rebuild your project
117143
118144
![Set Profiling Options in Nuclei Studio](images/profiling_options_in_ide.png)
119145
@@ -153,6 +179,8 @@ include $(NUCLEI_SDK_ROOT)/Build/Makefile.base
153179
> - Profiling and coverage analysis require significant memory
154180
> - Use ``DOWNLOAD=sram`` or ``DOWNLOAD=ddr`` for sufficient runtime memory
155181
> - When using ``-coverage`` flag, heap space may be insufficient - consider ``DOWNLOAD=ddr``
182+
> - Increase heap size explicitly if your application or test case uses gcov/gprof buffers heavily
183+
> - Avoid `DOWNLOAD=ilm` for such examples unless you have verified the available memory is still sufficient
156184
>
157185
> **Optimization Considerations:**
158186
> - Use ``-O0`` optimization level for accurate profiling results
@@ -161,6 +189,10 @@ include $(NUCLEI_SDK_ROOT)/Build/Makefile.base
161189
> **Extension Compatibility:**
162190
> - When using Zc extension with ``-pg``, note that ``-fomit-frame-pointer`` (enabled by Zc) is incompatible with ``-pg``
163191
> - You may need to adjust compiler flags accordingly
192+
>
193+
> **Scope of Instrumentation:**
194+
> - Set `APPDIRS` or equivalent build rules so that `-pg` and `-coverage` are added only to the target application sources
195+
> - Do not enable these flags for the whole SDK by default
164196
165197
### Step 2: Customize gprof_stub.c (For Profiling Only)
166198

@@ -295,3 +327,78 @@ llvm-cov gcov *.gcda
295327
> - ``.gcda`` files: Runtime coverage data generated by your program execution (different format for GCC vs LLVM/Clang)
296328
> - ``.gcov`` files: Annotated source files generated by gcov tools showing line-by-line coverage
297329
> - GCC and LLVM/Clang generate incompatible ``.gcda`` formats - use the corresponding toolchain's gcov tool
330+
331+
## FAQ
332+
333+
### Why do I see garbled coverage or profiling dump output, or partial dump logs?
334+
335+
In most cases, this means the runtime memory is insufficient, especially heap space used by gcov or gprof internal buffers.
336+
337+
Typical symptoms include:
338+
339+
- Dump output looks truncated, corrupted, or mixed with unexpected text
340+
- Coverage dump starts but does not complete correctly
341+
- Runtime errors disappear after increasing heap size
342+
343+
Check the following first:
344+
345+
- Make sure the application has enough heap, not only enough stack
346+
- Verify the actual available SRAM size in your project
347+
- 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
348+
349+
The `demo_profiling` example is typically run with `DOWNLOAD=sram` or `DOWNLOAD=ddr` so that more runtime memory is available for profiling experiments.
350+
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.
351+
352+
### Why are `gmon.out` or `*.gcda` files not generated when I use console or UART output?
353+
354+
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.
355+
356+
That means:
357+
358+
- UART or console output alone does not create `gmon.out` or `*.gcda` files automatically
359+
- You must save the dump log first
360+
- Then run `parse.py` on the host to reconstruct the binary profiling or coverage files
361+
362+
Example:
363+
364+
```bash
365+
python3 /path/to/Components/profiling/parse.py prof.log
366+
```
367+
368+
If you want the files to be written directly to the host filesystem, use interface `1` with semihosting enabled instead.
369+
370+
### What does `_mcleanup: tos overflow` usually mean?
371+
372+
This error typically indicates a profiling configuration problem, and the first items to check are:
373+
374+
- Heap is still too small for profiling runtime allocation
375+
- `-pg` or `-coverage` was applied to the wrong scope
376+
- Too much code was instrumented instead of only the target application
377+
378+
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.
379+
380+
### Should I add `-pg` and `-coverage` to the whole SDK or all source files?
381+
382+
No. These flags should only be added to the application code you want to analyze.
383+
384+
Do not enable them globally for:
385+
386+
- The whole SDK
387+
- All middleware
388+
- All BSP or driver code
389+
- Unrelated libraries
390+
391+
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.
392+
393+
### I already configured heap to 2 KB, 20 KB, or 40 KB. Why can it still fail?
394+
395+
Because the configured heap number alone is not enough evidence that the runtime can actually allocate that much memory.
396+
397+
Please verify:
398+
399+
- The linker script really leaves enough heap region at runtime
400+
- `_sbrk` is implemented correctly
401+
- Stack, heap, and other runtime sections are not overlapping
402+
- Your SDK port uses the same memory layout assumptions as the Nuclei SDK example
403+
404+
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.

doc/source/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ This is release version of ``0.9.0`` of Nuclei SDK.
255255
- Add LLVM/Clang ``-coverage`` option support in ``gcov.c`` with comprehensive Doxygen-style documentation
256256
- Fix printf format specifiers in ``gcov.c`` and ``gprof.c`` for better portability
257257
- Enhance profiling component documentation with GCC/LLVM toolchain support matrix, usage guide and result analysis examples
258+
- Enhance ``Components/profiling/README.md`` with integration reminders and FAQ entries for common profiling/coverage issues, including limiting ``-pg``/``-coverage`` to target application sources, heap sizing considerations, standalone component reuse, console dump parsing via ``parse.py``, and troubleshooting dump corruption or ``_mcleanup: tos overflow`` errors
258259
- Improve profiling component ``_mcount`` function documentation in ``Components/profiling/gprof.c`` with detailed RISC-V calling convention explanation and LLVM bug workaround (https://github.com/llvm/llvm-project/issues/121103)
259260

260261
V0.8.1

doc/source/design/app.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2197,6 +2197,19 @@ console when main part code is executed.
21972197
For detailed toolchain-specific command-line analysis instructions, see the IDE configuration steps below
21982198
and :ref:`demo_profiling_cmdline_usage`.
21992199

2200+
.. warning::
2201+
2202+
To reduce integration issues when using profiling or coverage:
2203+
2204+
* Add ``-pg`` or ``-coverage`` only to the application source files you want to analyze.
2205+
Do not enable these options globally for the whole SDK or unrelated libraries.
2206+
* Profiling and coverage may require a large heap. In the linker script, ``__HEAP_SIZE``
2207+
is only the minimum reserved heap size. The actual heap available to ``malloc`` is bounded
2208+
by ``__heap_start`` and ``__heap_end``, so it also depends on the linker layout, stack placement,
2209+
and remaining RAM.
2210+
* If you use console/UART dump mode, the run will not directly create ``gmon.out`` or ``*.gcda``.
2211+
You must save the dump log and run ``Components/profiling/parse.py`` to reconstruct these files.
2212+
22002213
Import or download Nuclei SDK 0.6.0 or later release NPK in Nuclei Studio, and then create a
22012214
project called ``demo_profiling`` based on ``app-nsdk_demo_profiling`` using
22022215
``Create Nuclei RISC-V C/C++ Project`` Wizard as below:
@@ -2291,6 +2304,11 @@ To use the profiling and code coverage features from the command line:
22912304
- When using ``-coverage`` flag, the application requires more memory to store coverage data.
22922305
You may need to change the ``DOWNLOAD`` variable in the Makefile from ``sram`` to ``ddr``
22932306
to ensure sufficient memory is available.
2307+
- ``__HEAP_SIZE`` in the linker script is only the minimum reserved heap size. The effective
2308+
heap available to ``malloc`` is determined by ``__heap_start`` and ``__heap_end``, so also
2309+
check the final linker layout and remaining RAM in your project.
2310+
- Apply ``APP_COMMON_FLAGS`` together with ``APPDIRS`` so profiling/coverage instrumentation
2311+
is limited to the target application source directories.
22942312

22952313
- When the Zc extension is used, ``-fomit-frame-pointer`` is passed by default, but
22962314
``-pg`` and ``-fomit-frame-pointer`` are incompatible. If you encounter issues, you may

0 commit comments

Comments
 (0)