Clang warning argument unused during compilation for -fsanitize-address-outline-instrumentation

I am trying to test out whether the flag -fsanitize-address-outline-instrumentation works for the LLVM Clang compiler.

Ubuntu clang version 15.0.7

I have created an exemplary program:

main.c

#include "stdio.h"

static inline void printFunc(void)
{
	printf("Test string \r\n");
}

int main(void)
{
	printFunc();

	return 0;
}

I wanted to verify whether the printFunc would be inlined or not, depeneding on whether the -fsanitize-address-outline-instrumentation compilation flag is added. When I try to compile the file, the compiler returns during compilation:

lukasz@lp:/tmp/test$ clang main.c -o main -fsanitize-address-outline-instrumentation
clang: warning: argument unused during compilation: '-fsanitize-address-outline-instrumentation' [-Wunused-command-line-argument]

I cannot figure out why is the parameter ignored. I would appreciate all help and feedback.

I believe it needs to be used together with -fsanitize=address, to turn on ASAN in the first place.

Hi and thank you for the answer. I think you are right! Now the binary generated with -fsanitize=address -fno-inline-functions OR -fsanitize=address -fsanitize-address-outline-instrumentation:

  • is larger,
  • yields different md5.

That’s not confirming via disassembly yet, but most likely that’s it.
But what’s interesting, is that the binary is actually larger… I was expecting it to be smaller and the code to run slower (due to function jump instead of inlined code):

lukasz@ce-lp:/tmp/test$ clang main.c -o main
lukasz@ce-lp:/tmp/test$ ls -l
total 20
-rwxrwxr-x 1 lukasz lukasz 16088 paĹş 13 20:02 main
-rw-rw-r-- 1 lukasz lukasz   136 paĹş 13 20:02 main.c
lukasz@ce-lp:/tmp/test$ clang main.c -o main -fsanitize=address -fsanitize-address-outline-instrumentation
lukasz@ce-lp:/tmp/test$ ls -l
total 1396
-rwxrwxr-x 1 lukasz lukasz 1424864 paĹş 13 20:02 main
-rw-rw-r-- 1 lukasz lukasz     136 paĹş 13 20:02 main.c

Any ideas?

-fsanitize-address-outline-instrumentation doesn’t control the inlining of your code, it controls the inlining of the instrumentation code added by Address Sanitizer.

So, we might expect -fsanitize=address -fsanitize-address-outline-instrumentation to produce a smaller binary than just -fsanitize=address, but both will be larger than a binary compiled without -fsanitize=address (due to the presence of the instrumentation code at all).

I see, thank you for the additional explanation. So given this, what is the right way in Clang, to tell the compiler to not inline any user functions? Like an equivalent of -noinline in GCC?

I think -fno-inline-functions should do it.

based on my tests:

  • -fno-inline-functions alone does nothing,
  • -fsanitize-address-outline-instrumentation alone does nothing,
  • -fsanitize=address -fno-inline-functions OR -fsanitize=address -fsanitize-address-outline-instrumentation do the same thing (the binary is the same larger size for both).

so some uncertainty here…

@HighCommander4 furthermore, the output binary size changes even after adding -fsanitize=address alone. After running the compilation again this time with -fsanitize=address -fno-inline-functions, the size doesnt change:

lukasz@ce-lp:/tmp/test$ clang main.c -o main -fsanitize=address
lukasz@ce-lp:/tmp/test$ ls -l
total 1396
-rwxrwxr-x 1 lukasz lukasz 1424864 paĹş 14 15:57 main
-rw-rw-r-- 1 lukasz lukasz     136 paĹş 13 20:02 main.c
lukasz@ce-lp:/tmp/test$ clang main.c -o main -fsanitize=address -fno-inline-functions
lukasz@ce-lp:/tmp/test$ ls -l
total 1396
-rwxrwxr-x 1 lukasz lukasz 1424864 paĹş 14 15:57 main
-rw-rw-r-- 1 lukasz lukasz     136 paĹş 13 20:02 main.c

So it seems that the -fno-inline-functions does not really change anything…

I mentioned that this is expected, because Address Sanitizer adds instrumentation code.

To be clear, though, -fno-inline-functions does not require -fsanitize=address and has nothing to do with Address Sanitizer. If you’re interested in seeing the effects of inlining vs. not inlining, there is no reason to use Address Sanitizer, it likely just adds a confounding variable.

I assume by that you mean it has no effect on the binary size on the code example you gave above?

Have you looked at the assembly to see whether inlining happens in each case?

Maybe the compiler is ignoring the inline (which at the end of the day is just a hint to the compiler), and not inlining the function even with default flags.

1 Like

Ok, this is clear and I set it aside.

I assume by that you mean it has no effect on the binary size on the code example you gave above?
Have you looked at the assembly to see whether inlining happens in each case?

Each test I check the following cases:

  • output binary size,
  • output binary md5,
  • output binary objdump -d redirected to file (for disassembly) and check size,
  • output binary objdump -d redirected to file (for disassembly) and check md5,

It was always the same for cases with and without -fno-inline-functions.

Maybe the compiler is ignoring the inline (which at the end of the day is just a hint to the compiler), and not inlining the function even with default flags.

I was considering this one too. As a consequence I thought: “if that’s the case, maybe I could force inlining with -finline-functions?”, but that did not work out either…

Thank you for all your feedback and responsiveness. Tomorrow I will document the tests more thorough- compare with GCC and also document the results in a public google sheet.

Do you have any suggestions for a proof of concept code that would “force” Clang to 100% inline something, for the sake of testing? I was assuming that my printFunc was a pretty good candidate for being inlined, but maybe I am wrong.

I don’t know to much about these specific flags. But I think you need to maybe have some -O flags to make sure the inliner even runs. Retry the tests with -O2.

1 Like

Good point. Will retest, thanks.

@tobiashieta that was the case. After adding -O2 I could see that:

  • compilation run with optimization + -fno-inline-functions yield a disassembled code that had the printFunc symbol.
  • compilation run with optimization only yield a disassembled code that had no printFunc symbol.

Thank you both @HighCommander4 and @tobiashieta

1 Like