2016-08-16 4 views
8

ओएस लिखने के प्रयास में, मुझे कार्य स्विचिंग के लिए वर्तमान फ़ंक्शन के अंत (एपिलॉग से ठीक पहले) का पता प्राप्त करने की आवश्यकता है।
कंक्रीटली मेरी समस्या है कि ईआईपी को कॉपी किए गए स्टैक के अंदर मेरे नव निर्मित कार्य (प्रक्रिया) को असाइन करना है। मैं पहले से ही एक प्रक्रिया के लिए रजिस्टरों को सहेजने/पुनर्स्थापित करने में कामयाब रहा हूं, लेकिन मुझे यह पता लगाना होगा कि बच्चे की प्रक्रिया में ईआईपी में क्या मूल्य होगा।जीसीसी - लेबल पता वास्तविक लेबल पते के बजाय वर्तमान ईआईपी लौटाता है

मैं सी मानक के जीसीसी के एक्सटेंशन का इस्तेमाल किया: Labels as Values और Local Labels
प्रलेखन से: आप एकल ऑपरेटर '& &' के साथ एक लेबल वर्तमान समारोह में परिभाषित के पते (या एक से युक्त समारोह) मिल सकता है। मान प्रकार शून्य है *।
और: जीसीसी आपको किसी भी नेस्टेड ब्लॉक स्कोप में स्थानीय लेबल घोषित करने की अनुमति देता है। एक स्थानीय लेबल एक साधारण लेबल की तरह है, लेकिन आप इसे केवल उस ब्लॉक के भीतर संदर्भित कर सकते हैं (एक गोटो स्टेटमेंट के साथ, या अपना पता ले कर) जिसमें इसे घोषित किया गया है।

pid_t fork(void) 
{ 
    __label__ fork_end; 
    ... 
    task->regs.eip = (uintptr_t)&&fork_end; 
    ... 
    return task->pid; 
    fork_end:; 
} 

जीसीसी यह संकलन, बस अमानक कोड के बारे में चेतावनी के साथ करता है।
लेकिन जब disassembled, gdb पता चलता है:

task->regs.eip = (uintptr_t)&&fork_end; 
0x00105008 <+87>: mov $0x105008,%edx 
0x0010500d <+92>: mov -0xc(%ebp),%eax 
0x00105010 <+95>: mov %edx,0x40(%eax) 
... 
    fork_end:; 
    } 
0x00105096 <+229>: leave 
0x00105097 <+230>: ret 

मैं उम्मीद task->regs.eip = (uintptr_t)&&fork_endl0x00105096 बजाय 0x00105008 को बचाने के लिए।
CFLAGS-O0 -std=gnu99 -fgnu89-inline -DDEBUG -ggdb3 -ffreestanding -fbuiltin हैं (चेतावनियां संबंधित विकल्प यहां नहीं दिखाए गए हैं)।

__label__ fork_end; टिप्पणी कुछ भी नहीं बदलता है।

+1

कृपया '&&' के बारे में जीसीसी दस्तावेज का संदर्भ प्रदान करें और बताएं कि यह आपकी समझ में क्या करता है। एक्सटेंशन का उपयोग करते समय यह चेतावनी नहीं देता है। [पूछें] देखें और सभी आवश्यक जानकारी प्रदान करें। – Olaf

+0

संपादित, और @ ओलाफ, जीसीसी ने '-Wpedantic' विकल्प के साथ गैर-मानक कोड के बारे में चेतावनी दी है। आपकी सलाह के लिए धन्यवाद। – Aerath

+0

आह, मैं देखता हूं। एक्सटेंशन के साथ '-Wpedantic' का उपयोग करना एक बुरा विचार की तरह ध्वनि। वैसे भी, आपकी कास्ट कार्यान्वयन को परिभाषित किया गया है और एक 'uint32_t' को पॉइंटर रखने के लिए तैयार नहीं किया गया है, न ही 1: 1 असाइनमेंट है। 64 बिट सिस्टम पर आप पहले ही बस्टेड हैं। कम से कम सही प्रकार का प्रयोग करें। किसी भी कारण से आप एक सूचक के रूप में 'शून्य *' का उपयोग नहीं करते हैं, लेकिन एक पूर्णांक? – Olaf

उत्तर

1

ऐसा प्रतीत होता है कि संकलक पूरी तरह से लेबल को अनुकूलित कर रहा है क्योंकि कोई कोड पथ कभी भी इसकी ओर जाता है। मैंने पुष्टि की है कि लेबल को return कथन से पहले ले जाना और यह सुनिश्चित करना कि असाइनमेंट और लेबल परिणामों के बीच वास्तविक कोड है जो मुझे विश्वास है कि आपका वांछित व्यवहार है। यहाँ कोड मैं परीक्षण करने के लिए एक साथ रखा है:

void *fork(void) { 
    __label__ fork_end; 
    void *test = &&fork_end; 

    test++; 

    fork_end: 
    return test; 
} 

इस आधार पर, मैं उम्मीद करेंगे आप वास्तव में से तुम क्या चाहते प्राप्त कर सकते हैं कि थोड़ा फिर से काम कर अपने कोड पथ सुनिश्चित करना है कि लेबल बिंदु किसी भी द्वारा पहुंचा जा सकता है कोड पथ

+0

चूंकि कॉलर प्रक्रिया से इस लेबल तक पहुंचने की उम्मीद नहीं की जाती है, इसलिए मुझे जीसीसी की चाल करने के लिए कभी भी सच नहीं होना चाहिए और इसे तब तक पहुंचने के रूप में देखा जा सकता है, भले ही यह न हो। वैसे भी आपको बहुत धन्यवाद @ जोएल-सी – Aerath

संबंधित मुद्दे