DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • What Do You Mean by Debugging in C?
  • Complete Guide to Open Source Licenses for Developers
  • How to Set up TestCafe and TypeScript JavaScript End-to-End Automation Testing Framework From Scratch
  • Getting Started With WebdriverIO Typescript Jasmine

Trending

  • Scaling in Practice: Caching and Rate-Limiting With Redis and Next.js
  • Scalable System Design: Core Concepts for Building Reliable Software
  • Stateless vs Stateful Stream Processing With Kafka Streams and Apache Flink
  • From Fragmentation to Focus: A Data-First, Team-First Framework for Platform-Driven Organizations

GNU Static Stack Usage Analysis

Stack overflows can be really detrimental. Learn how to analyze those GNU static stacks and properly analyze them in this great tutorial.

By 
Erich Styger user avatar
Erich Styger
·
Sep. 02, 15 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
11.3K Views

Join the DZone community and get the full member experience.

Join For Free

Stack overflows are a big problem: If I see a system crash, the first thing usually is I try to increase the stack size to see if the problem goes away. The GNU linker can check if my global variables fit into RAM. But it cannot know how much stack I need. So how cool would it be to have a way to find out how much stack I need?

Static Stack Usage Analysis with GNU

And indeed, this is possible with the GNU tools (e.g. I’m using it with the GNU ARM Embedded (launchpad) 4.8 and 4.9 compilers :-). But it seems that this ability is not widely known?

Overview

One approach I have used for a very long time is:

  1. Fill the memory of the stack with a defined pattern.
  2. Let the application run.
  3. Check with the debugger how much of that stack pattern has been overwritten.

That works pretty good. Except it is very empirical. What I need is some numbers from the compiler to have a better view.

In this article I present an approach with GNU tools plus Perl script to report the stack usage in the application.

GNU -fstack-usage Compiler Option

The GNU compiler suite has an interesting option: -fstack-usage

“A unit compiled with -fstack-usage will generate an extra file that specifies the maximum amount of stack used, on a per-function basis. The file has the same basename as the target object file with a .su extension.” (https://gcc.gnu.org/onlinedocs/gnat_ugn/Static-Stack-Usage-Analysis.html)

If I add that option to the compiler settings, there is now a .su (Stack Usage) file together with each object (.o) file:

Stack Usage File

The files are simple text files like this:

main.c:36:6:bar    48    static
main.c:41:5:foo    88    static
main.c:47:5:main    8    static

It lists the source file (main.c), the line (35) and column (5) position of the function, the function name (bar), the stack usage in bytes (48) and the allocation (static, this is the normal case).

Creating Stack Report

While the .su files already is a great source of information on a file/function basis, how to combine them to get the full picture? I have found a Perl script (avstack.pl) developed by Daniel Beer (see http://dlbeer.co.nz/oss/avstack.html).

From the original script, you might need to adapt the $objdump and $call_cost. With $objdump I specify the GNU objdump command (make sure it is present in the PATH) and $call_cost is a constant value added to the costs for each call:


my $objdump = "arm-none-eabi-objdump";
my $call_cost = 4;

Call avstack.pl with the list of object files, e.g.

avstack.pl ./Debug/Sources/main.o ./Debug/Sources/application.o

:idea: You need to list all the object files, the script does not have a feature to use all the .o files in a directory. I usually put the call to the Perl file into a batch file which I call from a post-build step (see “Executing Multiple Commands as Post-Build Steps in Eclipse“).

This generates a report like this:

  Func                               Cost    Frame   Height
------------------------------------------------------------------------
> main                                176       12        4
  foo                                 164       92        3
  bar                                  72       52        2
> INTERRUPT                            28        0        2
  __vector_I2C1                        28       28        1
  foobar                               20       20        1
R recursiveFunct                       20       20        1
  __vector_UART0                       12       12        1

Peak execution estimate (main + worst-case IV):
  main = 176, worst IV = 28, total = 204
  • The function names with a ‘>’ in front show ‘root’ functions: they are not called from anywhere else (maybe I have not passed all the object files, or are really not used).
  • If the function is recursive, it is marked with ‘R’. The cost estimate will be for a single level of recursion.
  • Cost shows the cumulative stack usage (this function plus all the callees).
  • Frame is the stack size used as in the .su file, including $call_cost constant.
  • Height indicates the number of call levels which are caused by this function.

Notice the INTERRUPT entry: it is the level of stack needed by the interrupts. The tool assumes non-nested interrupts: it counts the worst case Interrupt Vector (IV) stack usage to the peak execution:

Peak execution estimate (main + worst-case IV):
  main = 176, worst IV = 28, total = 204

What is counted as interrupt routine is controlled by this part in the Perl script, so every function starting with __vector_ is treated as interrupt routine:


# Create fake edges and nodes to account for dynamic behaviour.
$call_graph{"INTERRUPT"} = {};

foreach (keys %call_graph) {
    $call_graph{"INTERRUPT"}->{$_} = 1 if /^__vector_/;
}

Assembly Code

If I have inline assembly and assembly code in my project, then the compiler is not able to report the stack usage. These functions are reported with ‘zero’ stack usage:

  Func                               Cost    Frame   Height
------------------------------------------------------------------------
> HF1_HardFaultHandler                  0        0        1

The compiler will warn me about it:

stack usage computation not supported for this target

:idea: I have not found a way to provide that information to the compiler in the source.

RTOS Tasks

The tool works nicely and out-of-the box for tasks in an RTOS (e.g. FreeRTOS) based system. So with the tool I get a good estimate of each task stack usage, but I need to count to that value the interrupt stack usage:

  Func                               Cost    Frame   Height
------------------------------------------------------------------------
> ShellTask                           712       36       17

-Wstack-usage Warning

Another useful compiler option is -Wstack-usage. With this option the compiler will issue a warning whenever the stack usage exceeds a given limit.

Option to warn about stack usage

That way I can quickly check which functions are exceeding a limit:

stack usage warning

Summary

The GNU compiler suite comes with the very useful option -fstack-usage which produces text files for each compilation unit (source file) listing the stack usage. These files can be processed further, and I’m using the great Perl script created by Daniel Beer (Thanks!). With the presented tools and techniques, I get an estimate of the stack usage upfront. I’m aware that this is an estimate only, that recursion is only counted at a minimum level, and that assembly code is not counted in. I might extend the Perl file to scan folders for all the object files in it, unless someone already did this? If so, please post a comment and share :-).

GNU Object file

Published at DZone with permission of Erich Styger, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • What Do You Mean by Debugging in C?
  • Complete Guide to Open Source Licenses for Developers
  • How to Set up TestCafe and TypeScript JavaScript End-to-End Automation Testing Framework From Scratch
  • Getting Started With WebdriverIO Typescript Jasmine

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!