จำกัด โครงสร้าง C บางส่วนเพื่ออาศัยอยู่ในภูมิภาคเฉพาะของกอง
เมื่อใช้ C เพื่อใช้งานรันไทม์สำหรับภาษาการเขียนโปรแกรมเราอาจต้องการแยกแยะโครงสร้างข้อมูลรันไทม์ภายใน (จัดสรรโดยใช้ malloc / free หรือ Memory Pool บางชนิดหรืออาจจะเป็น mmap จากภาพที่ถูกทิ้ง) จากวัตถุผู้ใช้ที่จัดสรรในกอง GC ที่จัดการ
ในโมโนรันไทม์แสดงถึงวัตถุที่ได้รับการจัดการที่ได้มาจาก System.Object โดยใช้โครงสร้าง C struct typedef struct _MonoObject { ... } MonoObject โมโนใช้การประชุมที่คลาส dervies จากคลาส T หากสมาชิกคนแรกเป็นประเภท T:
struct _MonoString {
MonoObject obj ; /* System.String derives from System.Object */
...
}; โมโนกำลังเปลี่ยนไปใช้ระบอบการปกครองที่ตัวชี้ไปยังหน่วยความจำที่ได้รับการจัดการ 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 ที่ติดตั้ง (ไม่ว่าจะเป็นระบบหรือใน 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 ก่อนรหัสผู้ใช้ หากวิ่งจาก Sandbox ดังกล่าวข้างต้นคำสั่ง cabal run centrinel จะทำให้แน่ใจว่า Centrinel สามารถค้นหาไฟล์นี้ได้ หากคุณใช้ cabal install ส่วนหัว Centrinel จะถูกคัดลอกไปยังไดเรกทอรีข้อมูล Cabal และ centrinel Binary ที่สร้างขึ้นจะอ้างถึงตำแหน่งนั้นแม้ว่าคุณจะย้ายไบนารีในภายหลัง
ส่วนหัวนี้กำหนด __CENTRINEL__ ถึง 1 เพื่อระบุว่า centrinel กำลังทำงานอยู่ __CENTRINEL_MANAGED_ATTR ATTRIBUTE และ __CENTRINEL_MANAGED_REGION ตัวระบุแอตทริบิวต์ที่คุณสามารถใช้เพื่อเพิ่มความหมายของโครงสร้างของคุณรวมถึงมาโครเพื่อกำหนดความเป็นต้นแบบ GCC บางอย่างที่ไม่เข้าใจโดย language-c
ส่วนหัวจะถูกรวมโดย Centrinel โดยอัตโนมัติคุณไม่จำเป็นต้องรวมไว้อย่างชัดเจน
ตอนนี้คุณควรจะสามารถเล่นกับมันได้โดยใช้ cabal run centrinel -- [ARGS] (หรือ cabal repl หากคุณต้องการเรียกใช้ขั้นตอนต่าง ๆ แยกต่างหาก) นอกจากนี้ยังมีสคริปต์ centrinelcc ซึ่งสามารถใช้เป็น CC ใน make เรียกใช้การแทนที่แบบดรอปอินสำหรับ gcc หรือ clang
การใช้งาน: centrinel [--output FILE] -- CFLAGS CFILE
โปรแกรมเข้าใจ modicum ของตัวเลือกบรรทัดคำสั่ง 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 คุณควรเขียน -- สองครั้ง: ครั้งเดียวสำหรับ Cabal และอีกครั้งสำหรับ Centrinel: cabal run -- -- -DFOO -I../.. c-examples/attrib.c )
การใช้งาน: centrinel [--output FILE] --project compile_commands.json
ฐานข้อมูลการรวบรวมเสียงดังคือไฟล์ 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 ใน Make scripts/centrinelcc สามารถใช้เป็นค่าของตัวแปร CC สำหรับ make มันจะเรียกใช้คอมไพเลอร์จริงก่อน (ระบุโดยตัวแปรสภาพแวดล้อม REAL_CC หรือ cc ถ้า unset) และหากการรวบรวมสำเร็จมันจะเรียกใช้ 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 หาก unset อีกวิธีหนึ่งในการระบุคอมไพเลอร์คือการใช้ตัวเลือก --use-cc CC ซึ่งมีความสำคัญเหนือกว่าตัวแปรสภาพแวดล้อม
การทดลอง : ด้วย --format json CENTRINEL จะเขียนผลการวิเคราะห์เป็นหยด JSON (ซึ่งรูปแบบค่อนข้างฟลักซ์ในขณะนี้) หยดอาจถูกบริโภคเช่น Centrinel-Report
ด้วย --exclude DIR (ซึ่งอาจระบุหลายครั้ง) ไฟล์อินพุตใด ๆ ที่อยู่ใน DIR หรือหนึ่งในไดเรกทอรีย่อยจะไม่ถูกวิเคราะห์ (ใช้งานได้ทั้ง -- CFLAGS CFILE และกับ --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 : ผลประโยชน์ทันทีหนึ่งคือหากการรวบรวมขยะเกิดขึ้นในขณะที่รหัสรันไทม์ดั้งเดิมกำลังทำงานอยู่เราไม่จำเป็นต้องตรึงวัตถุที่อ้างอิงซึ่งอาจลดการกระจายตัว