いくつかのC構造体を、ヒープの特定の領域に存在するように制限します。
Cを使用してプログラミング言語のランタイムを実装する場合、GCマネージドヒープに割り当てられたユーザーオブジェクトから、内部ランタイムデータ構造( malloc / freeまたはある種のメモリプール、またはおそらくダンプ画像からmmapを使用して割り当てられます)を区別することをお勧めします。
モノでは、ランタイムはc struct typedef struct _MonoObject { ... } MonoObjectを使用してSystem.Objectから派生する管理されたオブジェクトを表します。 Monoは、最初のメンバーがタイプTの場合、クラスTのクラスDerviesが次の場合を使用しています。
struct _MonoString {
MonoObject obj ; /* System.String derives from System.Object */
...
}; MonoはMonoObjectHandle h管理されたメモリモノMonoObject *ptrへのポインターに移行しています。
このパッケージは、Cファイルを分析して、管理されたメモリへの生のポインターが使用される場所を見つけるライブラリを提供します。
CentrinelとCentrinel-Reportを使用する方法は、BEARを使用してCompilerの呼び出しを傍受するAutoToolsプロジェクトをチェックする方法です。
# assuming you have GHC and cabal installed
$ pushd $CENTRINEL_DIR # go to the centrinel source directory
$ echo "Building Centrinel"
$ cabal sandbox init
$ cabal install happy
$ cabal install alex
$ cabal install --dependencies-only
$ cabal configure
$ cabal build
$ popd
$ echo Building project using "bear"
$ pushd $SRC_DIR
$ ./autoconf ...
$ bear make
# produces a compile_commands.json file
$ popd
$ cd $CENTRINEL_DIR
$ curl -o centrinel-report.tar.gz https://github.com/lambdageek/centrinel-report/releases/download/v0.3.1/centrinel-report.tar.gz
$ tar xvzf centrinel-report.tar.gz
# writes a skeleton HTML report to centrinel-report/
$ cabal run centrinel -- --project $SRC_DIR/compile_commands.json --exclude $SRC_DIR/thirdparty --format json --output centrinel-report/centrinel-report.json
# produces centrinel-report/centrinel-report.json
$ cd centrinel-report && python -m SimpleHTTPServer 8000
# go look at http://localhost:8000/
これは早期の開発プロトタイプであるため、セットアップは少し関与しています。
最近のGHC(GHC 8.2.x、GHC 8.0.x、7.10.xでテスト)およびCabalが必要です。
依存関係:このプログラムでは、Carsingにlanguage-cライブラリを使用します - alex Lexerとhappy Parserがインストールされる必要があります(このリポジトリのSystemwideまたはSandboxに)。以下の手順では、サンドボックスを設定し、必要なプログラムをインストールします。 (アナライザーバイナリを構築するためだけに、 alexと分析を実行する必要はありませhappy 。)
git clone https://github.com/lambdageek/centrinel.git
cd centrinel
cabal sandbox init
cabal install happy
cabal install alex
cabal install --dependencies-only
cabal configure
cabal build
cabal run centrinel -- --helpinclude/centrinel.hヘッダーCentrinelは、いくつかの__attribute__((...))属性に依存しており、一部のプリプロセッサはそれを分析するものを伝えるために定義します。便利な場合、CentrinelがC Preprocessorを呼び出すと、ユーザーコードの前にファイルinclude/centrinel.h自動的に含めます。上記のように、サンドボックスから実行されている場合、 cabal run centrinelコマンドは、Centrinelがこのファイルを見つけることができることを保証します。代わりにcabal installを使用する場合、CentrinelヘッダーはCabal Data Directoryにコピーされ、構築されたcentrinelバイナリは、その後バイナリを移動してもその場所を参照します。
このヘッダーは、 __CENTRINEL__ 1から1に定義して、Centrinelが実行されていることを示します。 __CENTRINEL_MANAGED_ATTR属性と__CENTRINEL_MANAGED_REGION属性仕様は、構造体とマクロを注釈に使用してlanguage-cによって理解されていない特定のGCCプリミティブを定義します。
ヘッダーはCentrinelに自動的に含まれているため、明示的に含める必要はありません。
これで、 cabal run centrinel -- [ARGS] (またはさまざまなステップを個別に実行したい場合はcabal repl )を使用して、それを回ることができるはずです。さらに、 gccまたはclangのドロップイン置換としてInvocationsをmake際にCCとして使用できるスクリプトcentrinelccがあります。
使用法: centrinel [--output FILE] -- CFLAGS CFILE
このプログラムは、 -Dや-Iおよび-Uなどのccコマンドラインオプションのほんの一部を理解しており、他のものをプリプロセッサに渡します。前処理には意味がないいくつかのオプション( -cや-MTなどが理解され、静かに削除されます)。デフォルトでは、分析結果がstdoutに印刷されます。それらをファイルに指示するには、A --output FILEオプションを追加します。
$ cabal run centrinel -- c-examples/attrib.c
Errors:
c-examples/attrib.c:28: (column 2) [WARNING] >>> Region mismatch: Region 1 and Region 2
Additional locations:
c-examples/attrib.c:8: (column 2)
c-examples/attrib.c:13: (column 1)
c-examples/attrib.c:27: (column 1)
c-examples/attrib.c:35: (column 5) [ERROR] >>> Naked pointer(s) to managed object(s) found in declaration
Pointer to managed heap XP
in 0th argument 'x' at c-examples/attrib.c:35: (column 13)
in function declaration 'foo'
c-examples/attrib.c:37: (column 11) [ERROR] >>> Naked pointer(s) to managed object(s) found in declaration
Pointer to managed heap struct Y *
in return type
in function declaration 'bar'
Pointer to managed heap XP
in 1st argument 'x' at c-examples/attrib.c:37: (column 26)
in function declaration 'bar'
c-examples/attrib.c:39: (column 5) [ERROR] >>> Naked pointer(s) to managed object(s) found in declaration
Pointer to managed heap XP
in 0th argument 'x' at c-examples/attrib.c:33: (column 28)
in type defined at c-examples/attrib.c:33: (column 1)
at c-examples/attrib.c:39: (column 10)
in 0th argument 'f' at c-examples/attrib.c:39: (column 19)
in function declaration 'baz'
注:ダッシュから始まるオプションを渡す必要があり- cabal runを使用している場合は、2回--必要があります。カバルの場合は1回、Centrinel: cabal run -- -- -DFOO -I../.. c-examples/attrib.c )
使用法: centrinel [--output FILE] --project compile_commands.json
Clangコンパイルデータベースは、コンパイラの呼び出しのセットを指定するJSONファイルです。 cmakeやBearなどのツールを使用して、コンパイルデータベース(通常はcompile_commands.jsonと呼ばれる)を生成できます。 Centrinelは、 --projectオプションでデータベースを使用できます。
$ bear make -C some_project_directory # Note: doesn't work on OSX with System Integrity Protection
$ cabal run centrinel -- --project compile_commands.json
CCを交換しますファイルscripts/centrinelcc makeのCC変数の値として使用できます。最初にリアルコンパイラ( REAL_CC環境変数によって指定され、 cc )を実行し、コンパイルが成功した場合、 centrinel (パス上にある必要があります)を呼び出します
これらの手順はまだ自動化されていません
$ cabal install
$ cp dist/build/centrinel/centrinel [somewhere on your PATH]
$ cp scripts/centrinelcc [somewhere on your PATH]
$ export REAL_CC=/path/to/your/cc # if unset, defaults to 'cc'
$ make CC=centrinelcc
デフォルトでは、CentrinelはREAL_CC環境変数の値を使用して、 ccを実行します。コンパイラを指定する別の方法は、環境変数よりも優先される--use-cc CCオプションを使用することです。
実験: --format json Centrinelでは、分析結果をJSON Blob(現在の形式は非常に流動的なもの)として書き込みます。 BLOBは、たとえばCentrinel Reportなどで消費される場合があります
--exclude DIR (複数回指定される場合がある)を使用すると、 DIRまたはそのサブディレクトリの1つにある入力ファイルは分析されません。 (両方で動作します-- CFLAGS CFILEモードと--project JSON_FILEで)。
struct定義に関する領域の注釈( __attribute__((__region(N)))を整数nで指定)は、structの最初のメンバー(別のstructタイプである場合)に対して推測される領域と統一され、競合が報告されます。
領域__CENTRINEL_MANAGED_REGION ( include/centrinel.hの__region(1)として定義される)の構造物へのポインターは、関数プロトタイプ(宣言または定義)のどこかで発生する場合、エラーを誘発します。
__CENTRINEL_MANAGED_REGIONポインターを使用するための関数本体のチェック。
__CENTRINEL_SUPPRESS_ATTR(1)を使用してエラーなしでポインターをマネージドヒープに操作できる祝福された機能/構造体に注釈を付ける方法:
{
l: __CENTRINEL_SUPPRESS_ATTR ( 1 ) ;
/* your code that manipulated managed objecs */
} int __CENTRINEL_SUPPRESS_ATTR ( 1 ) foo (...); /* no warnings about pointers in ... */__CENTRINEL_SUPPRESS_ATTR(0)を使用して、抑制されたコンテキスト内でチェックを再開することができます。これは、たとえばマクロの拡張に役立ちます。マクロの本体を信頼したいので、ポインターチェックが抑制されますが、議論は抑制されていないため、チェックされます。1 :当面の利点の1つは、ネイティブランタイムコードの実行中にガベージコレクションが発生した場合、参照されるオブジェクトをピン留めする必要がないことです。これにより、断片化が減少する可能性があります。 ↩