Skip to content

Instantly share code, notes, and snippets.

@simonhf
Created February 3, 2020 21:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonhf/2a7b7eb98d2a10c549e8cc858bbefd53 to your computer and use it in GitHub Desktop.
Save simonhf/2a7b7eb98d2a10c549e8cc858bbefd53 to your computer and use it in GitHub Desktop.
Why does musl printf() use so much more stack when printfing floating point numbers?

Why does musl printf() use so much more stack when printfing floating point numbers?

How to test?

  • Create a small test program and run it with different configurations.

Run the test program on Ubuntu with glibc

$ gcc           -O0 -o svnprintf svnprintf.c && ./svnprintf
- main() starting
- found paint smudge 1008 bytes into stack
- foo
- found paint smudge 168 bytes into stack
- foo sp=0x7ffd37682110
- found paint smudge 1800 bytes into stack
- foo sp=0x7ffd37682110 sp=0x7ffd37682110
- found paint smudge 1800 bytes into stack
- foo5(): !!1 <= !!2 (=0x7ffd37682126) <= !!3; 1.00% 2
- found paint smudge 2240 bytes into stack
- foo6(): 1.000000
- found paint smudge 2208 bytes into stack
- main() ending

Run the test program on Ubuntu with mpaland printf

$ gcc -DMPALAND -O0 -o svnprintf svnprintf.c && ./svnprintf
- main() starting
- found paint smudge 1008 bytes into stack
- foo
- found paint smudge 648 bytes into stack
- foo sp=00007FFC1C7B7680
- found paint smudge 912 bytes into stack
- foo sp=00007FFC1C7B7680 sp=00007FFC1C7B7680
- found paint smudge 912 bytes into stack
- foo5(): !!1 <= !!2 (=00007FFC1C7B7696) <= !!3; 1.00% 2
- found paint smudge 976 bytes into stack
- foo6(): 1.000000
- found paint smudge 800 bytes into stack
- main() ending

Run test test program on Alpine Linux with musl

$ gcc           -O0 -o svnprintf svnprintf.c && ./svnprintf
- main() starting
- found paint smudge 1008 bytes into stack
- foo
- found paint smudge 168 bytes into stack
- foo sp=0x7ffd47ba8e40
- found paint smudge 976 bytes into stack
- foo sp=0x7ffd47ba8e40 sp=0x7ffd47ba8e40
- found paint smudge 976 bytes into stack
- foo5(): !!1 <= !!2 (=0x7ffd47ba8e56) <= !!3; 1.00% 2
- found paint smudge 8792 bytes into stack
- foo6(): 1.000000
- found paint smudge 8728 bytes into stack
- main() ending

Run test test program on Alpine Linux with mpaland printf

$ gcc -DMPALAND -O0 -o svnprintf svnprintf.c && ./svnprintf
- main() starting
- found paint smudge 1008 bytes into stack
- foo
- found paint smudge 592 bytes into stack
- foo sp=00007FFCB19D4E90
- found paint smudge 840 bytes into stack
- foo sp=00007FFCB19D4E90 sp=00007FFCB19D4E90
- found paint smudge 840 bytes into stack
- foo5(): !!1 <= !!2 (=00007FFCB19D4EA6) <= !!3; 1.00% 2
- found paint smudge 904 bytes into stack
- foo6(): 1.000000
- found paint smudge 728 bytes into stack
- main() ending

Results

  • Stack usage printf()ing one float:
| OS     |  printf |  size |
| ------ | ------- | ----- |
| Ubuntu |   glibc | 2,208 |
| Ubuntu | mpaland |   800 |
| Alpine |    musl | 8,728 |
| Alpine | mpaland |   728 |
  • Why does musl-libc use so much more stack space than the other printf() implementations tested?
#include <stdio.h>
#include <alloca.h>
#include <stdlib.h>
// gcc -O0 -o svnprintf svnprintf.c && ./svnprintf
// gcc -DMPALAND -O0 -o svnprintf svnprintf.c && ./svnprintf
#ifdef MPALAND
void _putchar(char character) {
putchar(character);
}
#include "printf/printf.c" // see https://github.com/mpaland/printf
#endif
char * sp;
// see idea from: https://stackoverflow.com/questions/389219/how-to-determine-maximum-stack-usage
void paint_stack(void) {
sp = alloca(1) - 0;
for (int i = 0; i < 32768; i ++) {
sp[-i] = 0x55;
}
}
void paint_analysis(void) {
int i_hi = 0;
for (int i = 0; i < 32768; i ++) {
if (0x55 != sp[-i]) {
i_hi = i;
}
}
printf("- found paint smudge %d bytes into stack\n", i_hi);
}
void foo1(void) {
int my_size = 1000;
char * p = alloca(my_size);
for (int i = 0; i < my_size; i ++) {
p[i] = 1;
}
}
void foo2(void) {
printf("- foo\n");
}
void foo3(void) {
printf("- foo sp=%p\n", sp);
}
void foo4(void) {
printf("- foo sp=%p sp=%p\n", sp, sp);
}
void foo5(void) {
char s[] = "!";
#ifdef MPALAND
// see https://github.com/mpaland/printf/issues/71
printf("- foo5(): %s%s%u <= %s%s%u (=%p) <= %s%s%u; %.2f%% %.0f\n", s, s, 1, s, s, 2, s, s, s, 3, 1.0, 2.0);
#else
printf("- foo5(): %s%s%'u <= %s%s%'u (=%p) <= %s%s%'u; %'.2f%% %'.0f\n", s, s, 1, s, s, 2, s, s, s, 3, 1.0, 2.0);
#endif
}
void foo6(void) {
printf("- foo6(): %f\n", 1.0);
}
void main(void) {
printf("- main() starting\n");
paint_stack(); foo1(); paint_analysis();
paint_stack(); foo2(); paint_analysis();
paint_stack(); foo3(); paint_analysis();
paint_stack(); foo4(); paint_analysis();
paint_stack(); foo5(); paint_analysis();
paint_stack(); foo6(); paint_analysis();
printf("- main() ending\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment