Membatasi beberapa C struct untuk tinggal di daerah heap tertentu.
Saat menggunakan C untuk mengimplementasikan runtime untuk bahasa pemrograman, kami mungkin ingin membedakan struktur data runtime internal (dialokasikan menggunakan malloc / free atau semacam kumpulan memori atau mungkin mmap dari gambar yang dibuang) dari objek pengguna yang dialokasikan dalam tumpukan yang dikelola GC.
Dalam mono runtime mewakili objek yang dikelola yang berasal dari System.Object menggunakan c struct typedef struct _MonoObject { ... } MonoObject . Mono menggunakan Konvensi bahwa Destvies Kelas dari Kelas T Jika anggota pertamanya adalah Tipe T:
struct _MonoString {
MonoObject obj ; /* System.String derives from System.Object */
...
}; Mono beralih ke rezim di mana petunjuk ke memori yang dikelola MonoObject *ptr harus diakses oleh runtime internal secara tidak langsung melalui pegangan 1 : MonoObjectHandle h
Paket ini menyediakan perpustakaan yang menganalisis file C untuk menemukan tempat -tempat di mana pointer mentah ke memori yang dikelola digunakan.
Berikut adalah bagaimana orang dapat menggunakan centrinel dan centrinel-report memeriksa proyek AutoTools menggunakan beruang untuk mencegat doa kompiler 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/
Ini adalah prototipe pengembangan awal, jadi pengaturannya sedikit terlibat.
Anda akan memerlukan GHC baru -baru ini (diuji dengan GHC 8.2.x, GHC 8.0.x, dan 7.10.x) dan Cabal.
Ketergantungan: Program ini menggunakan pustaka language-c untuk parsing - Anda akan membutuhkan alex Lexer dan happy Parser diinstal (baik di seluruh sistem atau di kotak pasir untuk repositori ini). Langkah -langkah di bawah ini mengatur kotak pasir dan menginstal program yang diperlukan ke dalamnya. (Anda tidak perlu alex dan happy menjalankan analisis, hanya untuk membangun biner penganalisa.)
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 bergantung pada beberapa atribut __attribute__((...)) dan beberapa preprocessor mendefinisikan untuk mengatakan apa yang harus dianalisis. Sebagai kenyamanan, ketika Centrinel memohon preprocessor C, secara otomatis menyertakan file include/centrinel.h sebelum kode pengguna. Jika berjalan dari kotak pasir, seperti di atas, perintah cabal run centrinel akan memastikan bahwa Centrinel dapat menemukan file ini. Jika sebaliknya Anda menggunakan cabal install , header Centrinel akan disalin ke direktori data Cabal, dan biner centrinel yang dibangun akan merujuk ke lokasi itu bahkan jika Anda kemudian memindahkan biner.
Header ini mendefinisikan __CENTRINEL__ menjadi 1 untuk menunjukkan bahwa centrinel sedang berjalan; __CENTRINEL_MANAGED_ATTR atribut dan __CENTRINEL_MANAGED_REGION Atribut specifier yang dapat Anda gunakan untuk memberi anotasi struct Anda, serta makro untuk mendefinisikan primitif GCC tertentu yang tidak dipahami oleh language-c .
Header secara otomatis dimasukkan oleh Centrinel, Anda tidak harus memasukkannya secara eksplisit.
Anda sekarang harus dapat bermain -main dengannya menggunakan cabal run centrinel -- [ARGS] (atau cabal repl jika Anda ingin menjalankan berbagai langkah secara terpisah). Selain itu, ada skrip centrinelcc yang dapat digunakan sebagai CC dalam make doa sebagai pengganti drop-in untuk gcc atau clang .
Penggunaan: centrinel [--output FILE] -- CFLAGS CFILE
Program ini memahami sedikit opsi baris perintah cc seperti -D dan -I dan -U dan akan meneruskan orang lain ke preprocessor. Beberapa opsi yang tidak masuk akal untuk preprocessing (seperti -c atau -MT dipahami dan dijatuhkan secara diam -diam). Hasil analisis default dicetak ke stdout; Untuk mengarahkannya ke file, tambahkan opsi --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'
Catatan : Jika Anda perlu melewati opsi yang dimulai dengan tanda hubung - Anda menggunakan cabal run , Anda harus menulis -- kali: sekali untuk Cabal dan sekali untuk Centrinel: cabal run -- -- -DFOO -I../.. c-examples/attrib.c )
Penggunaan: centrinel [--output FILE] --project compile_commands.json
Database kompilasi dentang adalah file JSON yang menentukan satu set invokasi kompiler. Alat seperti cmake atau Bear dapat digunakan untuk menghasilkan database kompilasi (biasanya disebut compile_commands.json ). Centrinel dapat menggunakan database dengan opsi --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 di Make scripts/centrinelcc dapat digunakan sebagai nilai variabel CC untuk make . Ini pertama -tama akan menjalankan kompiler nyata (ditentukan oleh variabel lingkungan REAL_CC , atau cc jika tidak ada) dan jika kompilasi berhasil, itu akan memohon centrinel (yang harus berada di jalur)
Langkah -langkah ini belum otomatis
$ 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
Secara default centrinel akan menggunakan nilai variabel lingkungan REAL_CC untuk menjalankan preprocessor, atau cc jika tidak disetel. Cara lain untuk menentukan kompiler adalah menggunakan opsi --use-cc CC yang lebih diutamakan daripada variabel lingkungan.
Eksperimental : Dengan --format json Centrinel akan menulis hasil analisis sebagai gumpalan JSON (yang formatnya cukup fluks saat ini). Gumpalan dapat dikonsumsi, misalnya laporan sentrinel
Dengan --exclude DIR (yang dapat ditentukan beberapa kali), setiap file input yang ada di DIR atau salah satu subdirektori tidak akan dianalisis. (Bekerja dengan -- CFLAGS CFILE MODE DAN DENGAN --project JSON_FILE ).
Anotasi wilayah pada definisi struct (ditentukan oleh __attribute__((__region(N))) dengan integer n ) akan disatukan dengan daerah yang disimpulkan untuk anggota pertama dari struct (asalkan jenis struct lain) dan konflik akan dilaporkan.
Pointer ke struct di wilayah __CENTRINEL_MANAGED_REGION (didefinisikan sebagai __region(1) dalam include/centrinel.h ) akan menimbulkan kesalahan jika terjadi di mana saja dalam prototipe fungsi (baik deklarasi atau definisi).
Memeriksa Badan Fungsi untuk Penggunaan Pointers __CENTRINEL_MANAGED_REGION .
Cara anotasi fungsi/struct diberkati yang diizinkan untuk memanipulasi pointer ke tumpukan yang dikelola tanpa kesalahan menggunakan __CENTRINEL_SUPPRESS_ATTR(1) yang dapat diterapkan pada:
{
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) dapat digunakan untuk mengubah pemeriksaan kembali dalam konteks yang ditekan. Ini berguna untuk, misalnya, ekspansi makro: Anda ingin tubuh makro dipercaya, sehingga pemeriksaan pointer ditekan, tetapi argumennya tidak tertekan sehingga diperiksa.1 : Salah satu manfaat langsung adalah bahwa jika pengumpulan sampah terjadi saat kode runtime asli sedang berjalan, kita tidak perlu menyematkan objek yang dirujuk, yang dapat mengurangi fragmentasi. ↩