2009-11-20 4 views
8

मैं डिफ़ॉल्ट कोड और डेटा उपयोगकर्ता और कर्नेल सेगमेंट के अलावा विभिन्न सेगमेंट का उपयोग करके कुछ प्रयोग करने की कोशिश कर रहा हूं। मैं स्थानीय डिस्क्रिप्टर टेबल और संशोधित_एलडीटी सिस्टम कॉल के उपयोग के माध्यम से इसे प्राप्त करने की आशा करता हूं। सिस्टम कॉल के माध्यम से मैंने एलडीटी में एक नई प्रविष्टि बनाई है जो वैश्विक चर के आधार पते के साथ एक सेगमेंट डिस्क्रिप्टर है जिसे मैं "पृथक" और 4 बाइट्स की सीमा चाहता हूं।एलडीटी (स्थानीय वर्णनकर्ता तालिका) का उपयोग

मैं एक सी प्रोग्राम में इनलाइन असेंबली के माध्यम से अपने कस्टम एलडीटी प्रविष्टि के सेगमेंट चयनकर्ता के साथ डेटा सेगमेंट रजिस्टर लोड करने का प्रयास करता हूं, लेकिन जब मैं चर को एक्सेस करने का प्रयास करता हूं तो मुझे सेगमेंटेशन गलती मिलती है।

मेरा संदेह यह है कि मेरे वैश्विक चर के ऑफसेट के साथ कोई समस्या है, और जब पता की गणना की जाती है, तो यह मेरे कस्टम सेगमेंट की सीमा से अधिक है जिससे सीजी गलती हो जाती है।

क्या किसी को इस स्थिति के आसपास एक काम के बारे में पता है?

ओह, वैसे, यह लिनक्स में x86 आर्किटेक्चर पर है। यह मेरी पहली बार एक मंच पर इस तरह के एक प्रश्न पूछने के लिए है, इसलिए यदि कोई अन्य जानकारी है जो उपयोगी साबित हो सकती है, तो कृपया मुझे बताएं।

अग्रिम धन्यवाद।

संपादित करें: मुझे एहसास हुआ कि मैं शायद स्रोत कोड :)

struct user_desc* table_entry_ptr = NULL; 

/* Allocates memory for a user_desc struct */ 
table_entry_ptr = (struct user_desc*)malloc(sizeof(struct user_desc)); 

/* Fills the user_desc struct which represents the segment for mx */ 
table_entry_ptr->entry_number = 0; 
table_entry_ptr->base_addr = ((unsigned long)&mx); 
table_entry_ptr->limit = 0x4; 
table_entry_ptr->seg_32bit = 0x1; 
table_entry_ptr->contents = 0x0; 
table_entry_ptr->read_exec_only = 0x0; 
table_entry_ptr->limit_in_pages = 0x0; 
table_entry_ptr->seg_not_present = 0x0; 
table_entry_ptr->useable = 0x1; 

/* Writes a user_desc struct to the ldt */ 
num_bytes = syscall(__NR_modify_ldt, 
        LDT_WRITE, // 1 
        table_entry_ptr, 
        sizeof(struct user_desc) 
        ); 

asm("pushl %eax"); 
asm("movl $0x7, %eax"); /* 0111: 0-Index 1-Using the LDT table 11-RPL of 3 */ 
asm("movl %eax, %ds"); 
asm("popl %eax"); 

mx = 0x407CAFE; 

SEG गलती है कि पिछले अनुदेश पर होता है शामिल होना चाहिए।

उत्तर

6

मैं केवल अनुमान लगा सकता हूं, क्योंकि मेरे पास असेंबली उपलब्ध नहीं है।

मेरा अनुमान है कि यह है कि लाइन, जिस पर आप एक segfault मिल की तरह कुछ करने के लिए संकलित किया गया है:

mov ds:[offset mx], 0x407cafe 

कहाँ offset mx कार्यक्रम के डेटा सेगमेंट में mx को ऑफसेट है (अगर यह एक स्थिर चर है) या ढेर में (यदि यह एक स्वचालित चर है)। किसी भी तरह से, इस ऑफ़सेट की गणना संकलन समय पर की जाती है, और इसका उपयोग DS अंक के बावजूद किया जाएगा।

अब क्या तुम यहाँ किया है एक नया सेगमेंट जिसका आधार mx के पते पर और जिसका सीमा या तो 0x4 या 0x4fff (G-bit जो आप निर्दिष्ट नहीं किया है के आधार पर) है पैदा करते हैं।

तो G-bit 0 है, तो सीमा 0x4 है, और क्योंकि यह अत्यधिक संभावना नहीं है कि mx पतों 0x0 और मूल DS की 0x4 के बीच स्थित है है, जब आप नए खंड आप को पार कर रहे हैं अंदर mx के लिए पहुँच ऑफसेट सीमा।

यदि G-bit 1 है, तो सीमा 0x4fff है। अब आपको केवल segfault मिलेगा यदि मूल mx0x4fff से ऊपर स्थित था।

यह देखते हुए कि नए सेगमेंट के आधार mx पर है, तो आप ऐसा करके mx पहुँच सकते हैं:

mov ds:[0], 0x407cafe 

मैं नहीं जानता कि मैं कैसे, सी में यह है कि लिखने के बारे में जाना चाहते हैं।

+0

यह सही है। नए 'डीएस' * के सापेक्ष 'एमएक्स' * का पता अब' 0' है। अपने नए सेगमेंट डिस्क्रिप्टर को 'डीएस' में लोड करने के बजाय, आपको इसे 'ES' में लोड करना चाहिए और इसे एक्सेस करने के लिए सेगमेंट ओवरराइड का उपयोग करना चाहिए (लोडिंग' डीएस' आपके सी कोड में सभी * डेटा एक्सेस को प्रभावित करेगा)। – caf

+0

यह मैं क्या मिलता है जब मैं objdump साथ ELF एकत्रित न: 8048a48: C7 05 8C 9e 04 08 फ़े movl $ 0x3424cafe, 0x8049e8c 8048a4f: 24 34 यह मेरे लिए काफी नई विषय सामग्री तो मैं कर रहा हूँ है ca सुनिश्चित नहीं है कि कौन से बाइट्स सेगमेंट रजिस्टर ओवरराइड संशोधक के लिए उपयोग किए जाते हैं। साथ ही, असेंबली कोड में दिखाया गया पता डिफ़ॉल्ट डेटा सेगमेंट में ऑफसेट है? यदि ऐसा है तो मुझे उस स्थान को बदलने की आवश्यकता है जहां चर को प्रारंभ किया गया है? – Brian

+0

यह टूटना है: 'सी 7' 'एमओवी आर/एम 32, इम 32' के लिए ओपोड है। '05' एमओडी/आरएम बाइट है, जो कहता है कि मेमोरी ऑपरेंड केवल विस्थापन द्वारा संबोधित किया जाता है। विस्थापन निम्नलिखित चार बाइट्स में है: '0x08049e8c'। अगले चार बाइट तत्काल '0x3424cafe' हैं। इसका मतलब है कि डिफ़ॉल्ट डेटा सेगमेंट के अंदर 'एमएक्स' का ऑफसेट' 0x08049e8c' है, और यह उस नए 'डीएस' के अंदर ऑफ़सेट है जिसे आप एक्सेस कर रहे हैं। –

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