Coccinelle

Abdun Nihaal
https://nihaal.me
12 March 2022 at ILUGC
Creative Commons License

Introduction

Collateral evolution

  • Evolution in API that has to be propagated to all code

      - int some_fn(int a, int b, int c);
      + int some_fn(int a, int b);
    
  • Code refactor

      - int some_fn(int a, int b, int c);
      + int some_fn(int a, int c, int b);
    
  • Common bug fixes
    • Check return value for NULL

Problem

  • Same change at multiple places
  • Hard to do manually
  • Using regex tools too tedious

    • Sensitive to newline, tabspaces
    • Does not understand C syntax
    int foo(char* arg) {
      return 0;
    }
    
    int /* Hello */
    foo(char*
        arg) { return 0; }
    

Coccinelle

  • Coccinelle => Ladybug in French
  • Code matching and transformation tool
  • Understands C semantics
  • Written in OCaml
  • Can be used for
    • Semantic grep
    • Automated code transformation
    • Useful for collateral evolution

Coccinelle

  • Intraprocedural
  • No preprocessing
  • Two parts
    • SmPL Language
    • Command line tool spatch
  • Inputs: Code + Semantic Patch
  • Output: Patch or Transformed code

Spatch

  • Commandline tool
  • Usage
    • Print diff to stdout

        spatch --sp-file sempatch.cocci input.c
      
    • Output transformed file

        spatch --sp-file sempatch.cocci -o output.c input.c
      
    • Inplace transform

        spatch --sp-file sempatch.cocci --in-place input.c
      

SmPL

  • Semantic Patch Language
  • Looks like a patch

Patch

  • Line number based
  • Lines marked with +/- are modifications
  • Other lines give context
diff --git a/drivers/staging/r8188eu/core/rtw_mlme_ext.c b/drivers/staging/r8188eu/core/rtw_mlme_ext.c
index 27bfb43f306e..ceca6751cdee 100644
--- a/drivers/staging/r8188eu/core/rtw_mlme_ext.c
+++ b/drivers/staging/r8188eu/core/rtw_mlme_ext.c
@@ -7157,7 +7157,7 @@ static void _linked_rx_signal_strength_display(struct adapter *padapter)
           "UndecoratedSmoothedPWDB:%d\n", UndecoratedSmoothedPWDB);
 }

-static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
+static u8 chk_ap_is_alive(struct sta_info *psta)
 {
    u8 ret = false;

@@ -7221,7 +7221,7 @@ void linked_status_chk(struct adapter *padapter)
            bool is_p2p_enable = false;
            is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);

-           if (!chk_ap_is_alive(padapter, psta))
+           if (!chk_ap_is_alive(psta))
                rx_chk = _FAIL;

            if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)

Semantic patch

  • Works with semantics (not line numbers)
  • Insensitive to newline, tabs, comments
  • Generalized code change

Rule

  1. Metavariable declaration
  2. Matching and transformation rule

    @@
    // metavariable declaration
    @@
    // matching and tranformation rule
    

Metavariables

  • Abstract over
    • Constants
    • Expression
    • Identifier
    • Type
  • Enclosed by @@

Transformation rules

  • Special characters (when in column 0)
    • + Add lines
    • - Delete lines
    • * Highlight lines
    • (|) Disjunction

Special symbols

    • Matches any code (reachable from all code path)
  • <… code …>
    • Matches 0 or more times
  • <+… code …+>
    • Matches 1 or more times

Isomorphisms

  • Different code with same semantics
  • Eg: Pointer checking
    • !x
    • x != NULL
    • NULL != x
  • We can also specify custom isomorphisms
  • Default: /usr/lib/coccinelle/standard.iso

Rule chaining and dependency

  • Rules can be named: @rulename@
  • Metavariables can be referenced from different rules
  • Dependencies specified using depends

Embedding Python or OCaml code

  • We can embed Python or OCaml code
  • Example

    @r1@
    expression E;
    @@
    BIT(E)
    
    @script:python@
    exp << r1.E;
    @@
    print(exp)
    

Coccinelle in Linux Kernel

  • Used for
    • Changes in internal kernel APIs
    • Fixing bugs due to API misunderstanding
  • As of 2018, Over 5500 commits mention using Coccinelle
  • 72 coccinelle scripts in scripts/coccinelle
  • make coccicheck

Thanks!

Questions?