힙의 특정 영역에 상주하도록 일부 C 구조를 제한합니다.
프로그래밍 언어 용 런타임을 구현하기 위해 C를 사용하는 경우 GC 관리 힙에 할당 된 사용자 오브젝트에서 내부 런타임 데이터 구조 ( malloc / free 또는 일부 종류의 메모리 풀을 사용하여 mmap )를 구별 할 수 있습니다.
모노에서 런타임은 c 구조 typedef struct _MonoObject { ... } MonoObject 사용하여 System.Object 에서 파생 된 관리 객체를 나타냅니다. 모노는 첫 번째 멤버가 T 형인 경우 클래스 T 의 클래스 듀비라는 컨벤션을 사용합니다.
struct _MonoString {
MonoObject obj ; /* System.String derives from System.Object */
...
}; 모노는 핸들 1 : MonoObjectHandle h 를 통해 간접적으로 런타임 내부에 의해 관리되는 메모리에 대한 포인터 MonoObject *ptr 전환하는 정권으로 전환하고 있습니다.
이 패키지는 C 파일을 분석하여 관리되는 메모리에 대한 원시 포인터를 사용하는 장소를 찾는 라이브러리를 제공합니다.
다음은 Centrinel 및 Centrinel 보고서를 사용하여 Bear를 사용하여 AutoTools 프로젝트를 사용하여 C 컴파일러 호출을 가로 채립니다.
# 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이 필요합니다.
종속성 :이 프로그램은 C 구문 분석에 language-c 라이브러리를 사용합니다. alex Lexer 및 happy Parser가 설치되어 있어야합니다 (이 저장소의 시스템 전체 또는 샌드 박스에). 아래 단계는 샌드 박스를 설정하고 필요한 프로그램을 설치합니다. (분석기 이진을 구축하기 위해 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 전 프로세서를 호출 할 때 사용자 코드 전에 파일 include/centrinel.h 파일이 자동으로 포함됩니다. 위와 같이 샌드 박스에서 실행되는 경우 cabal run centrinel 명령은 Centrinel 이이 파일을 찾을 수 있도록합니다. 대신 cabal install 사용하는 경우 Centrinel 헤더가 Cabal Data Directory에 복사되며, 구축 된 centrinel Binary는 이후 바이너리를 이동하더라도 해당 위치를 나타냅니다.
이 헤더는 __CENTRINEL__ 1 정의하여 Centrinel이 실행되고 있음을 나타냅니다. __CENTRINEL_MANAGED_ATTR attribute 및 __CENTRINEL_MANAGED_REGION 속성 지정자는 문자와 마크로를 사용하여 language-c 가 이해하지 못하는 특정 GCC 프리미티브를 정의하기 위해 매크로를 사용할 수 있습니다.
헤더는 Centrinel에 자동으로 포함되므로 명시 적으로 포함 할 필요가 없습니다.
이제 cabal run centrinel -- [ARGS] (또는 다양한 단계를 개별적으로 실행하려면 cabal repl )을 사용하여 게임을 할 수 있어야합니다. 또한, gcc 또는 clang 의 드롭 인 make 로 CC 로 사용할 수있는 스크립트 centrinelcc 가 있습니다.
사용법 : centrinel [--output FILE] -- CFLAGS CFILE
이 프로그램은 -D 및 -I 및 -U 와 같은 cc 명령 줄 옵션을 이해하고 다른 사람들을 전처리업자에게 전달합니다. 전처리에 적합하지 않은 몇 가지 옵션 (예 : -c 또는 -MT 와 같은 이해가 이해되고 조용히 떨어집니다). 기본적으로 분석 결과는 stdout에 인쇄됩니다. 파일로 지시하려면 --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 사용하는 옵션 -- 통과 해야하는 경우 다음을 작성해야합니다 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 CC 변수의 make 으로 사용할 수 있습니다. 먼저 실제 컴파일러 ( REAL_CC 환경 변수 또는 UNSET 인 경우 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 환경 변수의 값을 사용하여 사전 처리기를 실행하거나 UNSET 인 경우 cc 실행합니다. 컴파일러를 지정하는 또 다른 방법은 환경 변수보다 우선하는 --use-cc CC 옵션을 사용하는 것입니다.
실험 : --format json Centrinel은 JSON Blob (현재 형식이 유동적 인 형식)로 분석 결과를 작성합니다. 블롭은 예를 들어 Centrinel-Report와 함께 소비 될 수 있습니다
--exclude DIR (여러 번 지정 될 수 있음)을 사용하면 DIR 또는 하위 디렉토리 중 하나에있는 입력 파일은 분석되지 않습니다. ( -- CFLAGS CFILE mode 및 --project JSON_FILE 과 함께 작동합니다).
구조물 정의에 대한 영역 주석 (정수 n 이있는 __attribute__((__region(N))) 에 의해 지정됨)는 구조물의 첫 번째 구성원 (다른 구조물 유형 인 경우)에 대해 추론 된 영역으로 통일되며 충돌이보고됩니다.
__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 : 한 가지 즉각적인 이점은 기본 런타임 코드가 실행 중에 쓰레기 수집이 발생하면 참조 된 객체를 고정 할 필요가 없어서 조각화를 줄일 수 있다는 것입니다. ↩