Pointer tagging เทคนิคการปรับปรุงหน่วยความจำที่บรรจุข้อมูลเพิ่มเติมลงในบิตของพอยน์เตอร์ที่ไม่ได้ใช้งาน ได้จุดประกายการถกเถียงอย่างเข้มข้นในหมู่นักพัฒนาเกี่ยวกับความปลอดภัยและความสามารถในการใช้งานข้ามแพลตฟอร์มต่างๆ การอภิปรายมุ่งเน้นไปที่จำนวนบิตที่สามารถใช้งานได้อย่างเชื่อถือได้โดยไม่ทำลายความเข้ากันได้เมื่อฮาร์ดแวร์มีวิวัฒนาการ
ความท้าทายด้านความเข้ากันได้ข้ามแพลตฟอร์ม
ข้อกังวลที่ใหญ่ที่สุดที่นักพัฒนาเผชิญคือความแตกต่างของบิตที่ใช้ได้ในสถาปัตยกรรมต่างๆ ในขณะที่บางแพลตฟอร์มรับประกัน 16 บิตในส่วนบนของพอยน์เตอร์ 64 บิต แพลตฟอร์มอื่นๆ อาจใช้บิตมากกว่านั้นอย่างมีนัยสำคัญสำหรับการกำหนดที่อยู่เมื่อเทคโนโลยีก้าวหน้า การแบ่งหน้า 5 ระดับของ Intel บนโปรเซสเซอร์เซิร์ฟเวอร์ใช้ 57 บิตแล้ว ทำให้เหลือบิตสำรองสำหรับการแท็กน้อยลง สิ่งนี้สร้างเป้าหมายที่เคลื่อนไหวสำหรับนักพัฒนาที่ต้องการให้โค้ดของพวกเขาทำงานได้อย่างเชื่อถือได้ในหลายแพลตฟอร์มและฮาร์ดแวร์รุ่นอนาคต
สถาปัตยกรรม ARM และ x86 ไม่เห็นพ้องต้องกันเสมอไปว่าบิตไหนปลอดภัยที่จะใช้ ทั้งสองได้เสนอมาตรฐานสำหรับ pointer tagging แต่มาตรฐานเหล่านี้ไม่ซ้อนทับกันอย่างสมบูรณ์ สิ่งนี้บังคับให้นักพัฒนาต้องเลือกระหว่างความเข้ากันได้สูงสุดและประสิทธิภาพที่เหมาะสม
บิตแท็กพอยน์เตอร์ที่ปลอดภัยตามแพลตฟอร์ม:
- ข้ามแพลตฟอร์มแบบระมัดระวัง: 6 บิต (ลำดับสูง)
- การรับประกันของ Linux x86/ARM : 16 บิต (ลำดับสูง)
- ตามการจัดตำแหน่ง (แพลตฟอร์มส่วนใหญ่): 3-4 บิต (ลำดับต่ำ)
- การแบ่งหน้า 5 ระดับของ Intel : ใช้ 57 บิต ทำให้พื้นที่แท็กที่ใช้ได้ลดลง
กฎความปลอดภัยหกบิต
ผ่านการวิเคราะห์อย่างระมัดระวังของเอกสารฮาร์ดแวร์และแผนงานอนาคต นักพัฒนาที่มีประสบการณ์บางคนได้ระบุเพียงหกบิตลำดับสูงว่าปลอดภัยอย่างเชื่อถือได้ในทุกแพลตฟอร์มปัจจุบันและที่วางแผนไว้ แนวทางอนุรักษ์นิยมนี้ให้ความสำคัญกับความเข้ากันได้มากกว่าการเพิ่มพื้นที่แท็กที่ใช้ได้ให้สูงสุด
จำนวนบิตสูงสุดที่สามารถแท็กได้อย่างเชื่อถือได้ในทุกสภาพแวดล้อมและกรณีการใช้งานที่ผมสามารถกำหนดได้คือหกบิต คุณสามารถใช้มากกว่านั้นได้หรือไม่? อาจจะได้ แต่มีสภาพแวดล้อมที่ระบุได้ที่มันจะระเบิดหากคุณทำเช่นนั้น
ข้อจำกัดนี้ทำให้นักพัฒนาที่หวังจะบรรจุข้อมูลมากขึ้นลงในพอยน์เตอร์ผิดหวัง แต่มันสะท้อนความเป็นจริงของการสนับสนุนการกำหนดค่าฮาร์ดแวร์และระบบปฏิบัติการที่หลากหลาย
แนวทางทางเลือกและวิวัฒนาการของฮาร์ดแวร์
นักพัฒนากำลังสำรวจกลยุทธ์ต่างๆ เพื่อหาทางออกจากข้อจำกัดเหล่านี้ บางคนมุ่งเน้นไปที่บิตการจัดตำแหน่งในส่วนล่างของพอยน์เตอร์ ซึ่งสามารถให้บิตที่เชื่อถือได้ 3-4 บิตในระบบส่วนใหญ่ คนอื่นๆ แนะนำให้ใช้การนำไปใช้เฉพาะแพลตฟอร์มที่ปรับตัวเข้ากับความสามารถของสถาปัตยกรรมแต่ละแบบแทนที่จะแสวงหาโซลูชันแบบเดียวเหมาะกับทุกคน
ฮาร์ดแวร์สมัยใหม่เริ่มจัดการกับความท้าทายเหล่านี้โดยตรง โปรเซสเซอร์ ARM ตอนนี้รวมคุณสมบัติ Pointer Authentication Code ( PAC ) และ Memory Tagging Extension ( MTE ) ที่ให้การสนับสนุนฮาร์ดแวร์อย่างเป็นทางการสำหรับ pointer tagging iPhone ของ Apple เปิดใช้งานคุณสมบัติเหล่านี้แล้ว ซึ่งบ่งบอกว่าอุตสาหกรรมกำลังเคลื่อนไปสู่โซลูชันที่เป็นมาตรฐาน
เทคนิคนี้ไม่ใหม่ - มันย้อนกลับไปถึงการนำ Lisp ไปใช้ในยุคแรกและถูกใช้อย่างมีชื่อเสียงใน Macintosh ต้นฉบับ ซึ่งบรรจุข้อมูลลงใน 8 บิตที่ไม่ได้ใช้ของที่อยู่ 24 บิต อย่างไรก็ตาม ความซับซ้อนในปัจจุบันมาจากการสร้างสมดุลระหว่างความต้องการประสิทธิภาพกับวิวัฒนาการที่คาดเดาไม่ได้ของแผนการกำหนดที่อยู่หน่วยความจำ
การสนับสนุนการแท็กพอยน์เตอร์ของฮาร์ดแวร์:
- ARM Pointer Authentication Code ( PAC ): การลงนามพอยน์เตอร์ที่ได้รับความช่วยเหลือจากฮาร์ดแวร์
- ARM Memory Tagging Extension ( MTE ): คุณสมบัติความปลอดภัยของหน่วยความจำแบบบิวท์อิน
- Apple iPhones : เปิดใช้งาน PAC / MTE โดยค่าเริ่มต้น
- Intel / AMD : มาตรฐานที่เสนอต่างๆ (ไม่ทับซ้อนกัน)
ข้อกังวลเรื่องพฤติกรรมที่ไม่ได้กำหนดไว้
นอกเหนือจากความเข้ากันได้ของฮาร์ดแวร์แล้ว นักพัฒนาต้องนำทางผ่านน่านน้ำที่ขุ่นข้นของมาตรฐานภาษา การจัดการพอยน์เตอร์ผ่านการดำเนินการบิตอยู่ในพื้นที่สีเทาของข้อกำหนด C++ ซึ่งพฤติกรรมอาจถูกกำหนดโดยการนำไปใช้แทนที่จะได้รับการรับประกัน สิ่งนี้เพิ่มอีกชั้นหนึ่งของความเสี่ยงสำหรับระบบการผลิตที่ต้องการเสถียรภาพระยะยาว
การถกเถียงเน้นย้ำความตึงเครียดพื้นฐานในการเขียนโปรแกรมระบบระหว่างการบีบประสิทธิภาพสูงสุดจากฮาร์ดแวร์และการรักษาโค้ดที่ทำงานได้อย่างเชื่อถือได้ในสภาพแวดล้อมต่างๆ เมื่อลำดับชั้นหน่วยความจำมีความซับซ้อนมากขึ้นและประสิทธิภาพแคชยังคงมีความสำคัญ เทคนิคการปรับปรุงเหล่านี้ยังคงมีความสำคัญแม้ว่าความจุหน่วยความจำทั้งหมดจะเพิ่มขึ้น
อ้างอิง: Pointer Tagging in C++: The Art of Packing Bits Into a Pointer