rizsotto / scan-build

Clang's scan-build re-implementation in python
Other
362 stars 34 forks source link

Add support for static analysis of cross compilation #100

Closed LDVG closed 6 years ago

LDVG commented 6 years ago

This adds the -analyzer-target option to specify target triple, which may be necessary when --use-cc or --use-c++ are cross compilers.

rizsotto commented 6 years ago

Thanks for this PR. I'm not really familiar with cross compilation, can you help me to understand why this change is necessary? My understanding was that the -target flag is already in the commands. What case it would not be?

LDVG commented 6 years ago

Absolutely! I'll try my best. I also recommend reading the original patch discussion when this option was added to the Perl version of scan-build.

When the compiler is is built as a cross compiler, it does not support the -target option. It only builds for the other target. For instance, if you pass -target to arm-none-eabi-gcc (or similar) you'll get an unrecognized command line option error. In contrast, clang is a cross-compiler which accepts a -target option.

Consider compiling the file below (example taken from the link above) with arm-none-eabi-gcc -c test.c

int main(int argc, char** argv)
{
  int a;  // garbage value
#if __arm__
  int *p = 0L;
  if (argc == 3) {
    a = *p;  // dereferencing null pointer
  }
#endif
  return a;
}

If we run this through scan-build without --analyzer-target, clang assumes that we are compiling for the default target and it is not catching the null pointer derefence.

$ scan-build -vvvv --use-cc=arm-none-eabi-gcc make 
[ ... ]
analyze-cc: DEBUG: run_command: exec command ['/usr/bin/clang-6.0', '-cc1', '-triple', 'x86_64-pc-linux-gnu',  ...
[ ... ]
analyze-cc: INFO: logging_analyzer_output: test.c:9:2: warning: Undefined or garbage value returned to caller
analyze-cc: INFO: logging_analyzer_output:         return a;
analyze-cc: INFO: logging_analyzer_output:         ^~~~~~~~
analyze-cc: INFO: logging_analyzer_output: 1 warning generated.

As you can see, clang is targeting x86_64-pc-linux-gnu instead of our intended target since -target cannot be specified in the actual build command.

Using the --analyzer-target option with our target triple, we instead see the following (correct) output

$ scan-build -vvvv --use-cc=arm-none-eabi-gcc --analyzer-target=arm-none-eabi make
[...]
analyze-cc: DEBUG: run_command: exec command ['/usr/bin/clang-6.0', '-cc1', '-triple', 'armv4t-none--eabi', ...
[...]
analyze-cc: INFO: logging_analyzer_output: test.c:7:7: warning: Dereference of null pointer (loaded from variable 'p')
analyze-cc: INFO: logging_analyzer_output:                 a = *p;
analyze-cc: INFO: logging_analyzer_output:                     ^~
analyze-cc: INFO: logging_analyzer_output: test.c:9:2: warning: Undefined or garbage value returned to caller
analyze-cc: INFO: logging_analyzer_output:         return a;
analyze-cc: INFO: logging_analyzer_output:         ^~~~~~~~
analyze-cc: INFO: logging_analyzer_output: 2 warnings generated.
rizsotto commented 6 years ago

Thanks @LDVG , will try to add a test case for it in the future. (Not sure though how CI jobs would run it?)

LDVG commented 6 years ago

Thank you for this project! Hm, not sure. Perhaps it could run the example above? Assert that without --analyzer-target, clang issues one warning and that with --analyzer-target, clang issues two warnings? No fancy cross compiler needed.