How to measure the amount of stack an arbitrary function call uses in C?

451 Views Asked by At

Our company bought a proprietary C function: we have a compiled library ProcessData.a and an interface file to call it:

# ProcessData.h
void ProcessData(char* pointer_to_data, int data_len);

We want to use this function on an ARM embedded CPU and we want to know how much stack space it might use.

Question: how to measure the stack usage of an arbitrary function?

What I tried so far is to implement the following helper functions:

static int* stackPointerBeforeCall;

void StartStackMeasurement(void) {
    asm ("mov %0, sp" : "=r"(stackPointerBeforeCall));
    // For some reason I can't overwrite values immediately below the
    // stack pointer. I suspect a return address is placed there.
    static int* pointer;
    pointer = stackPointerBeforeCall - 4;
    // Filling all unused stack space with a fixed constant
    while (pointer != &_sstack) {
        *pointer = 0xEEEEEEEE;
        pointer--;
    }
    *pointer = 0xEEEEEEEE;
}

void FinishStackMeasurement(void) {
    int* lastUnusedAddress = &_sstack;
    while (*lastUnusedAddress == 0xEEEEEEEE) {
        lastUnusedAddress++;
    }
    // Printing how many stack bytes a function has used
    printf("STACK: %d\n", (stackPointerBeforeCall-lastUnusedAddress)*sizeof(int));
}

And then use them just before and after the function call:

StartStackMeasurement();
ProcessData(array, sizeof(array));
FinishStackMeasurement();

But this seems like a dangerous hack - especially the part where I am subtracting 4 from the stackPointerBeforeCall and overwriting everything below. Is there a better way?

2

There are 2 best solutions below

0
kaios On

You can use getrusage which is a function that gets you the resource usage of your software, in particular ru_isrss which is

An integral value expressed the same way, which is the amount of unshared memory used for stack space

(source)

You can then compare it to the stack usage of your program with a mocked call to the library.

However, this will only work if your system has implemented ru_isrss (unlike linux), otherwise the field will be set to 0.

0
Erik Eidt On

Compile the program and analyze the assembly or machine code for the function in question.  Many functions use the stack in a static manner, and this static size can be reasoned by analysis of the compiled code.  Some functions dynamically allocate stack space based on some computation, usually associated with some input parameter.  In those cases, you'll see different instructions being used to allocate stack space, and will have to work back to reason how the dynamic stack size might be derived.

Of course, this analysis would have to be redone with updates to the function (library).