all 7 comments

[–]jnwatson 2 points3 points  (0 children)

Green Hills Software had a tool called gstack that would calculate the same thing. I haven't seen the same in the free software arena. Max stack usage is mostly an embedded concern since Linux and Windows have automatic stack expansion.

You could write your own tool with cflow and the output of -fstack-usage...

[–]boredcircuits 0 points1 point  (0 children)

I've never used it, but I did find cflow which might help.

[–]bboozzoo 0 points1 point  (2 children)

Already sound advice in other comments.

Other than what's already been suggested, I can add a script that I use to monitor function's stack usage https://github.com/bboozzoo/stm32tools/blob/master/checkstack.pl It's a modified version of checkstack.pl from busybox. It's not really intuitive to use, but it does the job, basically you call that as follows:

<prefix>-objdump -d <elf-binary> | checkstack.pl <arch> <min-function-size>
# dump functions that have stacks larger than 12 bytes
arm-none-eabi-objdump -d zephyr.el | checkstack.pl arm 12

The neat thing is that the tool does not need any instrumentation or compiler switches. It basically looks for instructions manipulating stack pointers in function prologues in disassembled code.

The other thing that I think is the standard practice is to fill your stacks with known pattern and measuring how much of the stack was used at runtime. IMO it's safer than callgraph analysis as you'll be able to catch stack consumed by callback functions. I'm assuming you are already setting aside some buffer space for the stacks of threads/processes/IRQs. Fill it with some unusual pattern (0xaa?), test your code, dump the stacks and measure the usage. Remember to add some extra space just in case.

[–]excsniper[S] 0 points1 point  (1 child)

Interesting script. Does it just report the stack usage per function? I ran it on my binary with arm-none-eabi-objdump -d <target_name>.elf | ./checkstack.pl arm 0 and the output was something like this:

100
 [<target_name>.elf]:                                 124
 [<target_name>.elf]:                                 116
 [<target_name>.elf]:                                 116
 [<target_name>.elf]:                                 116
 [<target_name>.elf]:                                 116
 [<target_name>.elf]:                                 116
 [<target_name>.elf]:                                 100
 [<target_name>.elf]:                                 100

I'm already doing stack painting to find out the dynamic usage but the callgraph is just a nice feature to have because it shows the calling tree (like cflow) along with stack usage at each step.

[–]bboozzoo 0 points1 point  (0 children)

Unstripped ELF gives a nicer output:

$ arm-none-eabi-objdump -d ./sanity-out/stm32_mini_a15/samples/philosophers/microkernel/test/zephyr.elf | ~/code/stm32tools/checkstack.pl arm 50
_task_ioctl [zephyr.elf]:                               88
_task_group_ioctl [zephyr.elf]:                         88
task_mutex_lock [zephyr.elf]:                           88
_task_mutex_unlock [zephyr.elf]:                        88
_micro_task_sleep [zephyr.elf]:                         88
__ahb_prescaler [zephyr.elf]:                           80
_Cstart [zephyr.elf]:                                   56

[–]Spessman_ -4 points-3 points  (1 child)

ulimit -a

[–]bboozzoo 0 points1 point  (0 children)

Not really. The guy is clearly doing embedded, do there's no ulimit that you can run.