mirror of
https://github.com/systemd/systemd.git
synced 2025-01-21 22:04:01 +03:00
c988ef4cf4
Turns out that the original way we did things was quite broken, as it skipped a _lot_ of code. This was because we just threw everything into one pile and tried to spatch it, but this made Coccinelle sad, like when man page examples redefined some of our macros, causing typedef conflicts. For example, with a minimal reproducer that defines a cleanup macro in two source files, Coccinelle has no issues when spatch-ing each one separately: $ spatch --verbose-parsing --sp-file zz-drop-braces.cocci main.c init_defs_builtins: /usr/lib64/coccinelle/standard.h HANDLING: main.c SPECIAL NAMES: adding _cleanup_ as a attribute with arguments SPECIAL NAMES: adding _cleanup_free_ as a attribute $ spatch --verbose-parsing --sp-file zz-drop-braces.cocci logcontrol-example.c init_defs_builtins: /usr/lib64/coccinelle/standard.h HANDLING: logcontrol-example.c SPECIAL NAMES: adding _cleanup_ as a attribute with arguments But when you try to spatch both of them at once, Coccinelle starts complaining and skipping the "bad" code: $ spatch --verbose-parsing --sp-file zz-drop-braces.cocci main.c logcontrol-example.c init_defs_builtins: /usr/lib64/coccinelle/standard.h HANDLING: main.c logcontrol-example.c SPECIAL NAMES: adding _cleanup_ as a attribute with arguments SPECIAL NAMES: adding _cleanup_free_ as a attribute remapping: _cleanup_ to an ident in macro name ERROR-RECOV: found sync end of #define, line 44 parsing pass2: try again ERROR-RECOV: found sync end of #define, line 44 parse error = File "logcontrol-example.c", line 44, column 21, charpos = 1719 around = '__attribute__', whole content = #define _cleanup_(f) __attribute__((cleanup(f))) badcount: 2 bad: #include <systemd/sd-journal.h> bad: BAD:!!!!! #define _cleanup_(f) __attribute__((cleanup(f))) This was, unfortunately, hidden as it is visible only with --verbose-parsing (or --parse-error-msg). Another issue was how we handled includes. The original way of throwing them into the pile of source files doesn't really work, leading up to similar issues as above. The better way is to let Coccinelle properly resolve all includes by telling it where to find our own include files (basically the same thing we already do during compilation). After fixing all this, Coccinelle now has a chance to process much more of our code (there are still some issues in more complex macros, but that requires further investigation). However, there's a huge downside from all of this - doing a _proper_ code analysis is surprisingly time and resource heavy; meaning that processing just one Coccinelle rule now takes 15 - 30 minutes. To make this slightly less painful, Coccinelle supports caching the generated ASTs, which actually helps a lot - it gets the runtime of one rule from 15 - 30 minutes down to ~1 minute. It, of course, has its own downside - the cache is _really_ big (ATTOW the cache takes ~15 GiB). However, even with the aggressive AST caching you're still looking at ~1 hour for one full Coccinelle run, which is a bit annoying, but I guess that's the price of doing things _properly_ (but I'll definitely look into ways of further optimizing this).