2015/11/21

[c/c++]静的解析ツールを探そう (1)

コンパイルが終わらないので、その間に静的解析ツールでも使ってみよう。
先に書いておくが、今回はInferをWindowsで動かすのはあきらめた。

  • Infer
    • 「分離理論」というものでやってる
    • ポインタを追うのが他の静的ツールよりも得意らしい
    • モバイル向けっぽいことを書いてあるけど、何がだろう?
  • Cppcheck
    • C++でも使える
  • Splint
    • LINTの中のLINTというイメージ(私の中で)

 

やってみる対象は、こちら。
https://github.com/hirokuma/nrf51822v10_bds_sample

ほとんどnRF51 SDKのサンプルなのだけど、まあよかろう。
GCCのビルドでは、-Wallくらいしかつけていないが警告は出ていない。

-DBOARD_BVMCN5102 -DSWI_DISABLE0 -DSOFTDEVICE_PRESENT -DNRF51 -DS110 -DBLE_STACK_SUPPORT_REQD -Wall -Werror -O0 -ggdb -Wno-error=format -mcpu=cortex-m0 -mthumb -mabi=aapcs --std=gnu99 -mfloat-abi=soft -ffunction-sections -fdata-sections -fno-strict-aliasing -fno-builtin --short-enums


Inferを試そうと、インストール方法のページを見た。
https://github.com/facebook/infer/blob/master/INSTALL.md#install-the-dependencies
うーん・・・、LinuxとMacOSはコンパイル済みのバイナリがあるけど、Windowsについては単語すら出てこない。
cygwinならLinuxと似たような環境でできるんじゃなかろうか、ということで、試すだけ試そう。

gccが4.7.2以上、Pythonが2.7以上なのはよいとして、opamってのも必要らしい。
cygwinのインストーラには、大文字でも小文字でもOPAのものがなかった。

cygwinでinfer入れた人いないの?と検索したら、こちらが出てきた。
http://fbinfer.com/support.html#faq
まあ、サポートしてないならないでもいいので、どこでダメになるか見てみよう。

cygwinとopamで検索すると、Ocamlが出てきた。
opamというのは、Ocamlのパッケージ管理ツールみたいだ。
Ubuntuのapt-get、pythonのpipみたいなものか。

Ocamlのインストールページを見る。
https://ocaml.org/docs/install.html
ここから、Ocaml on Windowsのページに飛んで、そこのインストーラをダウンロードするサイトに飛ぼうとすると、Firefoxが「危険!」と警告してきた。
gallium.inria.frというサイトがよろしくないらしい。

「君子、危うきに、近寄らず!」

私はその場を立ち去った。
まあ、君子かどうかは別として、そこまでしてWindowsで試さなくとも、というところだ。
今回はInferを見送って、Linuxを立ち上げるときに試そう。


次は、CppCheck。
これはCygwinのインストーラからでもインストールできるので楽だ。

CppCheckのよいところは、とりあえず解析してくれるところだ。

$ cppcheck --enable=all .
Checking main.c...
[main.c:178]: (style) The scope of the variable 'err_code' can be reduced.
Checking main.c: BLE_DFU_APP_SUPPORT...
1/3 files checked 63% done
Checking services/ble_adconvert_service.c...
2/3 files checked 90% done
Checking services/service_if.c...
3/3 files checked 100% done
[main.c:97]: (style) The function 'assert_nrf_callback' is never used.
[services/ble_adconvert_service.c:172]: (style) The function 'ble_adconvert_service_advalue_set' is never used.
[services/service_if.c:78]: (style) The function 'bluetooth_adc_send' is never used.
(information) Cppcheck cannot find all the include files (use --check-config for details)

インクルードパスとか、マクロの定義とかまったく与えていないのに、とりあえず調べてくれている。
うん、確かに「assert_nrf_callback」はいきなり出てくるから未使用とみなされて仕方ないし。
世話好きなおっちゃんが「うーん、わからんこともあるけど適当にやってみるわ」っていう印象。
悪い意味じゃなくてですな。

ここで引数にインクルードパスなどを設定していくのもよいが、せっかく「--check-configで詳細を見れるよ」って書いてあるので、見てみよう。

  1: $ cppcheck --enable=all --check-config .
  2: Checking main.c...
  3: [main.c:27]: (information) Include file: <stdint.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
  4: [main.c:28]: (information) Include file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
  5: [main.c:29]: (information) Include file: "nordic_common.h" not found.
  6: [main.c:30]: (information) Include file: "nrf.h" not found.
  7: [main.c:31]: (information) Include file: "app_error.h" not found.
  8: [main.c:32]: (information) Include file: "ble.h" not found.
  9: [main.c:33]: (information) Include file: "ble_hci.h" not found.
 10: [main.c:34]: (information) Include file: "ble_srv_common.h" not found.
 11: [main.c:35]: (information) Include file: "ble_advdata.h" not found.
 12: [main.c:36]: (information) Include file: "ble_advertising.h" not found.
 13: [main.c:37]: (information) Include file: "ble_conn_params.h" not found.
 14: [main.c:38]: (information) Include file: "boards.h" not found.
 15: [main.c:39]: (information) Include file: "softdevice_handler.h" not found.
 16: [main.c:40]: (information) Include file: "app_timer.h" not found.
 17: [main.c:41]: (information) Include file: "device_manager.h" not found.
 18: [main.c:42]: (information) Include file: "pstorage.h" not found.
 19: [main.c:43]: (information) Include file: "app_trace.h" not found.
 20: [main.c:44]: (information) Include file: "bsp.h" not found.
 21: [main.c:45]: (information) Include file: "bsp_btn_ble.h" not found.
 22: [main.c:46]: (information) Include file: "service_if.h" not found.
 23: 1/3 files checked 63% done
 24: Checking services/ble_adconvert_service.c...
 25: [services/ble_adconvert_service.h:6]: (information) Include file: <stdint.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
 26: [services/ble_adconvert_service.h:7]: (information) Include file: <stdbool.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
 27: [services/ble_adconvert_service.h:8]: (information) Include file: "ble.h" not found.
 28: [services/ble_adconvert_service.h:9]: (information) Include file: "ble_srv_common.h" not found.
 29: [services/ble_adconvert_service.h:10]: (information) Include file: "app_util_bds.h" not found.
 30: [services/ble_adconvert_service.c:4]: (information) Include file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
 31: [services/ble_adconvert_service.c:5]: (information) Include file: "nordic_common.h" not found.
 32: [services/ble_adconvert_service.c:6]: (information) Include file: "ble_srv_common.h" not found.
 33: [services/ble_adconvert_service.c:7]: (information) Include file: "app_util.h" not found.
 34: [services/ble_adconvert_service.c:8]: (information) Include file: "app_util_bds.h" not found.
 35: 2/3 files checked 90% done
 36: Checking services/service_if.c...
 37: [services/service_if.h:16]: (information) Include file: <stdint.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
 38: [services/service_if.h:17]: (information) Include file: "ble.h" not found.
 39: [services/service_if.c:4]: (information) Include file: <stdint.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
 40: [services/service_if.c:5]: (information) Include file: "app_error.h" not found.
 41: [services/service_if.c:6]: (information) Include file: "app_trace.h" not found.
 42: 3/3 files checked 100% done

たくさんある・・・。
まあ、何も指定していないので、当たり前だ。

 

まずは、Makefileを書き換える。
インクルードパスだけの変数と、マクロ定義だけの変数を作るようにするのだ。
そうしておくと、それをCppCheckに渡すことができる。
-Wallなんかは、CppCheckが理解できないので、分離するのだ。

そうして整理した結果をgithubにコミットした。

$ make check
Checking ../../../main.c...
[../../../main.c:178]: (style) The scope of the variable 'err_code' can be reduced.
1/3 files checked 63% done
Checking ../../../services/ble_adconvert_service.c...
2/3 files checked 90% done
Checking ../../../services/service_if.c...
3/3 files checked 100% done
[../../../main.c:97]: (style) The function 'assert_nrf_callback' is never used.
[../../../services/ble_adconvert_service.c:172]: (style) The function 'ble_adconvert_service_advalue_set' is never used.
[../../../services/service_if.c:78]: (style) The function 'bluetooth_adc_send' is never used.
(information) Cppcheck cannot find all the include files (use --check-config for details)

システム側のインクルードパスは、もう気にしないことにした。
本当は、コンパイラオプションから自動的に-Iを生成できればと思ったのだけど、うまくいかなかったのだ。


splintも、cppcheckと同じ文法でいけるかなー、と、何も考えずに試した。

$ make splint
Splint 3.1.2 --- 15 Sep 2012

../../../../../components/device/nrf51.h:146:40:
    #warning Not supported compiler type
  Preprocessing error. (Use -preproc to inhibit warning)
   In file included from ../../../../../components/device/nrf.h:44,
                 from ../../../main.c:30
../../../../../components/device/nrf51.h:1191:40:
    #warning Not supported compiler type
../../../../../components/libraries/trace/app_trace.h:47:29:
    Invalid character in macro parameter name
   In file included from ../../../main.c:43
../../../../../components/libraries/trace/app_trace.h:47:29:
    Parameter list for #define is not parseable
../../../../../components/libraries/trace/app_trace.h:48:28:
    Invalid character in macro parameter name
../../../../../components/libraries/trace/app_trace.h:48:28:
    Parameter list for #define is not parseable
../../../../../components/libraries/trace/app_trace.h:49:29:
    Invalid character in macro parameter name
../../../../../components/libraries/trace/app_trace.h:49:29:
    Parameter list for #define is not parseable
Preprocessing error for file: /cygdrive/e/Prog/BLE/nRF51_SDK_10.0.0_dc26b5e/proj
    ects/bds_test/main.c
*** Cannot continue.
Makefile:264: ターゲット 'splint' のレシピで失敗しました
make: *** [splint] エラー 1

まあ、そんなもんか。

コンパイラの種類が違う、というのは、gccじゃなくてsplintだから仕方なかろう。
「Invalid character」は、こういうので出ていた。

#define app_trace_init(...)

これはapp_trace.hの47行目だが、改行位置は28桁目になっている。
ファイルは0x0D/0x0Aで保存しているので、「改行は0x0A」という指摘なのか。
まあ、main.cが処理されなかったので、意味はないのだけどね。


いろいろ調べて疲れたので、今回はここまで。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。

注: コメントを投稿できるのは、このブログのメンバーだけです。