mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-30 18:41:11 +00:00
Indirect calls can be eliminated by adding corresponding annotations.
BUG=chromium:648840
BRANCH=none
TEST=extra/stack_analyzer/stack_analyzer_unittest.py
make BOARD=elm && extra/stack_analyzer/stack_analyzer.py \
--objdump=arm-none-eabi-objdump \
--addr2line=arm-none-eabi-addr2line \
--export_taskinfo=./build/elm/util/export_taskinfo.so \
--section=RW \
--annotation=./extra/stack_analyzer/example_annotation.yaml \
./build/elm/RW/ec.RW.elf
make BOARD=elm SECTION=RW \
ANNOTATION=./extra/stack_analyzer/example_annotation.yaml \
analyzestack
Change-Id: I18c317f9c6478b5b431ee04d882453791df27891
Signed-off-by: Che-yu Wu <cheyuw@google.com>
Reviewed-on: https://chromium-review.googlesource.com/631082
Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
73 lines
2.7 KiB
Markdown
73 lines
2.7 KiB
Markdown
Stack Size Analysis Tool for EC Firmware
|
|
========================================
|
|
|
|
This tool does static analysis on EC firmwares to get the maximum stack usage of
|
|
each function and task. The maximum stack usage of a function includes the stack
|
|
used by itself and the functions it calls.
|
|
|
|
Usage
|
|
-----
|
|
|
|
Make sure the firmware of your target board has been built.
|
|
|
|
In `src/platform/ec`, run
|
|
```
|
|
make BOARD=${BOARD} SECTION=${SECTION} ANNOTATION=${ANNOTATION} analyzestack
|
|
```
|
|
The `${SECTION}` can be `RO` or `RW`. The `${ANNOTATION}` is a optional
|
|
annotation file, see the example_annotation.yaml.
|
|
|
|
Output
|
|
------
|
|
|
|
For each task, it will output the result like below,
|
|
```
|
|
Task: PD_C1, Max size: 1156 (932 + 224), Allocated size: 640
|
|
Call Trace:
|
|
pd_task (160) [common/usb_pd_protocol.c:1644] 1008a6e8
|
|
-> pd_task[common/usb_pd_protocol.c:1808] 1008ac8a
|
|
- handle_request[common/usb_pd_protocol.c:1191]
|
|
- handle_data_request[common/usb_pd_protocol.c:798]
|
|
-> pd_task[common/usb_pd_protocol.c:2672] 1008c222
|
|
-> [annotation]
|
|
pd_send_request_msg.lto_priv.263 (56) [common/usb_pd_protocol.c:653] 1009a0b4
|
|
-> pd_send_request_msg.lto_priv.263[common/usb_pd_protocol.c:712] 1009a22e0
|
|
```
|
|
The `pd_task` uses 160 bytes on the stack and calls `pd_send_request_msg.lto_priv.263`.
|
|
|
|
The callsites to the next function will be shown like below,
|
|
```
|
|
-> pd_task[common/usb_pd_protocol.c:1808] 1008ac8a
|
|
- handle_request[common/usb_pd_protocol.c:1191]
|
|
- handle_data_request[common/usb_pd_protocol.c:798]
|
|
-> pd_task[common/usb_pd_protocol.c:2672] 1008c222
|
|
```
|
|
This means one callsite to the next function is at `usb_pd_protocol.c:798`,
|
|
but it is inlined to the current function and you can follow the trace:
|
|
`usb_pd_protocol.c:1808 -> usb_pd_protocol.c:1191 -> usb_pd_protocol.c:798` to
|
|
find the callsite. The second callsite is at `usb_pd_protocol.c:2672`. And the
|
|
third one is added by annotation.
|
|
|
|
The unresolved indirect callsites have the similar format to the above.
|
|
|
|
Annotating Indirect Call
|
|
------------------------
|
|
|
|
To annotate an indirect call like this,
|
|
```
|
|
Unresolved indirect callsites:
|
|
pd_transmit
|
|
-> pd_transmit[common/usb_pd_protocol.c:407] 802c9c8
|
|
- tcpm_transmit[driver/tcpm/tcpm.h:142]
|
|
```
|
|
It is an indirect call in the `tcpm_transmit`, which is inlined to the `pd_transmit`.
|
|
|
|
You can add a annotation like the below to eliminate it.
|
|
```
|
|
add:
|
|
tcpm_transmit[driver/tcpm/tcpm.h:142]:
|
|
- anx74xx_tcpm_transmit
|
|
```
|
|
The source `tcpm_transmit[driver/tcpm/tcpm.h:142]` must be a full signature (function_name[path:line number]).
|
|
So the resolver can know which indirect call you want to annotate and eliminate (even if it is inlined).
|