تقييد بعض الهياكل C للإقامة في مناطق محددة من الكومة.
عند استخدام C لتنفيذ وقت تشغيل لغة برمجة ، قد نرغب في التمييز بين هياكل بيانات وقت التشغيل الداخلية (المخصصة باستخدام malloc / free أو نوع من تجمع الذاكرة أو ربما mmap من صورة مصقولة) من كائنات المستخدم المخصصة في كومة GC المدارة.
في مونو ، يمثل وقت التشغيل الكائنات المدارة التي تستمد من System.Object باستخدام Crity typedef struct _MonoObject { ... } MonoObject . يستخدم Mono الاتفاقية التي تفيد بأن الفئة من الفئة T إذا كان عضوها الأول من النوع T:
struct _MonoString {
MonoObject obj ; /* System.String derives from System.Object */
...
}; ينتقل Mono إلى نظام حيث يجب الوصول إلى مؤشرات للذاكرة المدارة MonoObject *ptr بواسطة الداخلية في وقت التشغيل بشكل غير مباشر عبر المقابض 1 : MonoObjectHandle h
توفر هذه الحزمة مكتبة تحلل ملفات C للعثور على أماكن يتم فيها استخدام المؤشرات الأولية للذاكرة المدارة.
فيما يلي كيف يمكن للمرء أن يستخدم Centrinel و Centrinel Report ، تحقق من مشروع Autotools باستخدام Bear لاعتراض دعوات برنامج التحويل البرمجي 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.
التبعيات: يستخدم هذا البرنامج مكتبة language-c لتحليل 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 header يعتمد Centrinel على بعض سمات __attribute__((...)) ويحدد بعض المعالج المسبق أن يخبرها بما يجب تحليله. كراحة ، عندما تستدعي Centrinel المعالج المسبق C ، فإنه يتضمن تلقائيًا include/centrinel.h قبل رمز المستخدم. إذا تم تشغيله من صندوق الرمل ، على النحو الوارد أعلاه ، سيضمن قيادة cabal run centrinel أن Centrinel قادر على العثور على هذا الملف. إذا استخدمت بدلاً من ذلك cabal install ، فسيتم نسخ رأس Centrinel إلى دليل بيانات Cabal ، وسيشير الثنائي centrinel الذي تم إنشاؤه إلى هذا الموقع حتى لو قمت بعد ذلك بنقل الثنائي.
يحدد هذا الرأس __CENTRINEL__ إلى 1 للإشارة إلى أن Centrinel يعمل ؛ سمة __CENTRINEL_MANAGED_ATTR و __CENTRINEL_MANAGED_REGION تحددها يمكنك استخدامها للتعليق على بنياتك ، وكذلك وحدات الماكرو لتحديد بعض البدائل التي لا تُفهمها language-c .
يتم تضمين الرأس تلقائيًا بواسطة Centrinel ، ليس عليك تضمينه بشكل صريح.
يجب أن تكون قادرًا الآن على اللعب معها باستخدام cabal run centrinel -- [ARGS] (أو cabal repl إذا كنت ترغب في تشغيل الخطوات المختلفة بشكل منفصل). بالإضافة إلى ذلك ، هناك برنامج سينمائي centrinelcc يمكن استخدامه كـ CC في make كبديل للاستبدال لـ gcc أو clang .
الاستخدام: centrinel [--output FILE] -- CFLAGS CFILE
يتفهم البرنامج مجموعة من خيارات سطر أوامر cc مثل -D و -I و -U وسيتم نقلها إلى الآخرين إلى المعالج المسبق. بعض الخيارات التي لا معنى لها للمعالجة المسبقة (مثل -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 ، فيجب عليك الكتابة -- : مرة واحدة للكابال ومرة واحدة لـ 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 كقيمة متغير CC make . سيتم تشغيل المترجم الحقيقي أولاً (المحدد بواسطة متغير بيئة 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 (تنسيقها في التدفق في الوقت الحالي). قد يتم استهلاك النقطة ، على سبيل المثال التقارير Centrinel
باستخدام --exclude DIR (الذي يمكن تحديده عدة مرات) ، لن يتم تحليل أي ملفات إدخال موجودة في DIR أو واحدة من الدلائل الفرعية الخاصة به. (يعمل على حد سواء مع -- CFLAGS CFILE MODE ومع --project JSON_FILE ).
سيتم توحيد التعليقات التوضيحية للمنطقة على تعريفات البنية (المحددة بواسطة __attribute__((__region(N))) مع عدد صحيح n ) مع استنتاج مناطق للعضو الأول في البنية (شريطة أن يكون نوعًا آخر للهيكل) وسيتم الإبلاغ عن تعارضات.
ستؤدي المؤشرات للهياكل في المنطقة __CENTRINEL_MANAGED_REGION (المعرّفة على أنها __region(1) في include/centrinel.h ) إلى حدوث خطأ إذا حدث في أي مكان في نموذج أولي (إما إعلان أو تعريف).
التحقق من أجسام الوظائف لاستخدام مؤشرات __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 : إحدى الفوائد الفورية هي أنه في حالة حدوث مجموعة القمامة أثناء تشغيل رمز وقت التشغيل الأصلي ، لا يتعين علينا تثبيت الكائن المشار إليه ، مما قد يقلل من التفتت. ↩