HeadlinesBriefing favicon HeadlinesBriefing.com

GCC नेस्टेड फंक्शन ट्रैम्पोलिन स्टैक ऑप्टिमाइज़ेशन

Hacker News •
×

GCC नेस्टेड फंक्शन ट्रैम्पोलिन स्टैक ऑप्टिमाइज़ेशन। एक्ज़ीक्यूटेबल स्टैक के बिना GCC पर नेस्टेड फंक्शन की इनडायरेक्ट कॉलिंग। मार्टिन उएकर, 2026-08-29। हमने पिछली बार चर्चा की थी कि कैसे GCC और Clang पर नेस्टेड फंक्शन का उपयोग एक्ज़ीक्यूटेबल स्टैक की आवश्यकता के बिना कॉलबैक के लिए किया जा सकता है। लेकिन क्या होगा अगर किसी को GCC के पुराने संस्करणों का समर्थन करने की आवश्यकता है? बेशक, कोई केवल एक एक्ज़ीक्यूटेबल स्टैक स्वीकार कर सकता है, लेकिन एक हैक के साथ इससे बचना भी संभव है। GCC: नेस्टेड फंक्शन और ट्रैम्पोलिन। आइए पहले चर्चा करते हैं कि GCC नेस्टेड फंक्शन का पता लेने का समर्थन कैसे करता है। नए मैक्रोज़ के उपयोग के बिना हमारा खिलौना उदाहरण नीचे दिखाया गया है। x86_64 पर, जनरेटेड असेंबली स्टैक पर एक ट्रैम्पोलिन रखता है और इसे इनलाइन baz फंक्शन के माध्यम से तुरंत आमंत्रित करता है। ट्रैम्पोलिन एक छोटा कोड अनुक्रम है जो स्टेटिक फ्रेम रजिस्टर को स्टैक पर एक संरचना में लोड करता है जिसमें पैरेंट फंक्शन से कैप्चर किए गए वेरिएबल होते हैं और फिर लोकल फंक्शन पर कूदता है। यदि कोई स्थिरांक -17591, -17847, और -1864106167 को वापस असेंबली निर्देशों में अनुवाद करता है, तो निम्नलिखित x86_64 कोड प्राप्त होता है: movq $bar.0, %r11, movq $frame, %r10, jump *%r11। दोनों, स्टेटिक चेन और कोड एड्रेस, ट्रैम्पोलिन के कोड में मूव निर्देशों द्वारा उपयोग किए जाने वाले तत्काल स्थिरांक हैं। ट्रैम्पोलिन के एड्रेस का उपयोग करके फंक्शन को कॉल करने के बजाय, हम ट्रैम्पोलिन से कोड एड्रेस और स्टेटिक चेन निकाल सकते हैं और लोकल फंक्शन को सीधे कॉल करने के लिए उन्हें __builtin_call_with_static_chain बिल्ट-इन फंक्शन के साथ उपयोग कर सकते हैं। इस प्रकार, हम इन दो पॉइंटर मानों को ट्रैम्पोलिन से पढ़ने का उपयोग GCC के पुराने संस्करणों में एक फॉलबैक तंत्र के रूप में कर सकते हैं। नुकसान यह हैं कि एक ट्रैम्पोलिन अभी भी बनाया जाता है, कंपाइलर अभी भी इनडायरेक्ट कॉल को डिवर्चुअलाइज़ नहीं कर सकता है, और स्टैक को अभी भी एक्ज़ीक्यूटेबल के रूप में चिह्नित किया जाएगा। तो क्या हासिल हुआ? चूंकि हम कभी भी वास्तव में ट्रैम्पोलिन को आमंत्रित नहीं करते हैं, हम निम्नलिखित कमांड के साथ स्टैक को फिर से नॉन-एक्ज़ीक्यूटेबल बना सकते हैं, जो कम से कम इस सुविधा की सुरक्षा चिंताओं को संबोधित करता है। patchelf --clear-execstack program। यह विचार मेरी प्रायोगिक लाइब्रेरी, noplate में लागू किया गया है, जहां कोड एड्रेस और स्टेटिक चेन से एक वाइड पॉइंटर बनाया जाता है। ट्रैम्पोलिन्स एज़ फंक्शन डिस्क्रिप्टर्स। एक और विचार है जिसे मैं तलाशने लायक पाता हूं: कोई ट्रैम्पोलिन को स्वयं फंक्शन डिस्क्रिप्टर के रूप में भी उपयोग कर सकता है। ट्रैम्पोलिन बनाए जाने पर स्टेटिक चेन और कोड पॉइंटर निकालने के बजाय, हम हमेशा की तरह ट्रैम्पोलिन का एड्रेस पास करते हैं। लेकिन हर जगह जहां हम ट्रैम्पोलिन को कॉल कर सकते हैं, हम पहले जांचते हैं कि क्या पॉइंटर ट्रैम्पोलिन की ओर इशारा करता है, और फिर कोड एड्रेस और स्टेटिक चेन निकालकर __builtin_call_with_static_chain का उपयोग करके नेस्टेड फंक्शन को सीधे कॉल करते हैं। एक अर्थ में हम कह सकते हैं कि ट्रैम्पोलिन को आमंत्रित करने के बजाय, हम कॉल साइट पर एक सुपर सिंपल इंटरप्रेटर का उपयोग करके ट्रैम्पोलिन के कोड की व्याख्या कर रहे हैं जो केवल इस विशिष्ट कोड अनुक्रम की व्याख्या कर सकता है और जो इतना सरल है कि...