2011-09-23 18 views
16

का उपयोग कर सी/सी ++ कोड इंस्ट्रूमेंटिंग मैं सिर्फ एलएलवीएम प्रोजेक्ट के बारे में पढ़ता हूं और इसका उपयोग एलएलवीएम के फ्रंट एंड विश्लेषक क्लेंग का उपयोग करके सी/सी ++ कोड पर स्थिर विश्लेषण करने के लिए किया जा सकता है। मैं जानना चाहता था कि एलएलवीएम का उपयोग कर स्रोत कोड में स्मृति (चर, स्थानीय और वैश्विक) तक सभी पहुंच निकालना संभव है या नहीं।एलएलवीएम

क्या एलएलवीएम में कोई अंतर्निहित लाइब्रेरी मौजूद है जिसे मैं इस जानकारी को निकालने के लिए उपयोग कर सकता हूं। यदि नहीं, तो कृपया मुझे सुझाव दें कि ऐसा करने के लिए कार्यों को कैसे लिखना है। (मौजूदा स्रोत कोड, संदर्भ, ट्यूटोरियल, उदाहरण ...) मैंने जो सोचा है, क्या मैं पहले स्रोत कोड को एलएलवीएम बीसी में परिवर्तित कर दूंगा और फिर उपकरण यह विश्लेषण करने के लिए, लेकिन यह नहीं पता कि यह कैसे करना है।


मैं जो आईआर मैं अपने उद्देश्य के लिए उपयोग करना चाहिए अपने आप को यह पता लगाने की कोशिश की (बजना का सार सिंटेक्स पेड़ (एएसटी) या LLVM के सर्व शिक्षा अभियान के मध्यवर्ती प्रतिनिधित्व (आईआर)।), लेकिन वास्तव में जो करने के लिए एक को समझ नहीं सकता उपयोग। यहां मैं क्या करने की कोशिश कर रहा हूं। किसी भी सी/सी ++ प्रोग्राम (जैसा कि नीचे दिया गया है) दिया गया है, मैं स्मृति से/पढ़ने/लिखने वाले प्रत्येक निर्देश से पहले और बाद में कुछ फ़ंक्शन में कॉल डालने का प्रयास कर रहा हूं। उदाहरण के लिए नीचे दिए गए सी ++ प्रोग्राम (Account.cpp)

#include <stdio.h> 

class Account { 
    int balance; 

public: 
    Account(int b) { 
    balance = b; 
    } 

    int read() { 
    int r; 
    r = balance; 
    return r; 
    } 

    void deposit(int n) { 
    balance = balance + n; 
    } 

    void withdraw(int n) { 
    int r = read(); 
    balance = r - n; 
    } 
}; 

int main() { 
    Account* a = new Account(10); 
    a->deposit(1); 
    a->withdraw(2); 
    delete a; 
} 

तो इंस्ट्रूमेंटेशन के बाद मेरे कार्यक्रम की तरह दिखना चाहिए पर विचार करें:

#include <stdio.h> 

class Account { 
    int balance; 

public: 
    Account(int b) { 
    balance = b; 
    } 

    int read() { 
    int r; 
    foo(); 
    r = balance; 
    foo(); 
    return r; 
    } 

    void deposit(int n) { 
    foo(); 
    balance = balance + n; 
    foo(); 
    } 

    void withdraw(int n) { 
    foo(); 
    int r = read(); 
    foo(); 
    foo(); 
    balance = r - n; 
    foo(); 
    } 
}; 

int main() { 
    Account* a = new Account(10); 
    a->deposit(1); 
    a->withdraw(2); 
    delete a; 
} 

जहां foo() हो सकता है जैसे किसी भी समारोह मौजूदा सिस्टम का समय मिलता है या काउंटर में वृद्धि .. इतने पर। मैं समझता हूं कि उपर्युक्त कार्य को सम्मिलित करने के लिए मुझे पहले आईआर प्राप्त करना होगा और फिर आईआर पर एक उपकरण पास करना होगा जो आईआर में ऐसी कॉल डालेगा, लेकिन मुझे वास्तव में यह नहीं पता कि इसे कैसे प्राप्त किया जाए। कृपया मुझे उदाहरण के साथ सुझाव दें कि इसके बारे में कैसे जाना है।

यह भी समझता है कि एक बार जब मैं आईआर में प्रोग्राम संकलित करता हूं, तो मेरे मूल कार्यक्रम और वाद्य यंत्र आईआर के बीच 1: 1 मैपिंग प्राप्त करना वास्तव में मुश्किल होगा। तो, मूल कार्यक्रम में आईआर (उपकरण के कारण) में किए गए परिवर्तनों को प्रतिबिंबित करना संभव है।

एलएलवीएम पास के साथ शुरू करने के लिए और अपने आप को कैसे बनाना है, मैंने एक पास का एक उदाहरण देखा जो एलएलवीएम आईआर लोड और स्टोर्स में रन-टाइम चेक जोड़ता है, SAFECode का लोड/स्टोर इंस्ट्रूमेंटेशन पास (http://llvm.org/viewvc/llvm-project/safecode/trunk/include/safecode/LoadStoreChecks.h?view=markup और http://llvm.org/viewvc/llvm-project/safecode/trunk/lib/InsertPoolChecks/LoadStoreChecks.cpp?view=markup)। लेकिन मैं यह समझ नहीं पाया कि इस पास को कैसे चलाया जाए। कृपया मुझे बताएं कि कुछ कार्यक्रमों पर इस पास को कैसे चलाया जाए, ऊपर दिए गए खाते.cpp कहते हैं।

+1

क्या आपने पहले से ही एलएलवीएम उदाहरणों की जांच की है और क्या आपने एलएलवीएम पास को कार्यान्वित करने के तरीके को पढ़ा है (और उन्हें 'ऑप्ट' प्लगइन के रूप में चलाएं)? http://llvm.org/docs/WritingAnLLVMPass.html –

+0

[एलएलवीएम का उपयोग कर इंस्ट्रूमेंटिंग सी/सी ++ कोड का संभावित डुप्लिकेट] (http://stackoverflow.com/questions/7806689/instrumenting-cc-code-using-llvm) – RedX

उत्तर

28

सबसे पहले, आपको यह तय करना होगा कि आप क्लैंग या एलएलवीएम के साथ काम करना चाहते हैं या नहीं। वे दोनों बहुत अलग डेटा संरचनाओं पर काम करते हैं जिनके फायदे और नुकसान होते हैं।

आपकी समस्या के आपके स्पैर विवरण से, मैं एलएलवीएम में अनुकूलन पास के लिए जाने की अनुशंसा करूंगा। आईआर के साथ काम करना कोड को स्वच्छ करने, विश्लेषण करने और इंजेक्ट करने के लिए बहुत आसान बना देगा क्योंकि यही वह करने के लिए किया गया था। नकारात्मकता यह है कि आपकी परियोजना एलएलवीएम पर निर्भर होगी जो आपके लिए कोई समस्या नहीं हो सकती है या नहीं। आप सी बैकएंड का उपयोग करके परिणाम आउटपुट कर सकते हैं लेकिन यह मानव द्वारा उपयोग योग्य नहीं होगा।

ऑप्टिमाइज़ेशन पास के साथ काम करते समय एक और महत्वपूर्ण नकारात्मकता यह है कि आप मूल स्रोत कोड से सभी प्रतीकों को भी खो देते हैं। भले ही Value वर्ग (उस पर और अधिक) में getName विधि हो, तो आपको कभी भी पर कुछ भी अर्थपूर्ण रखने के लिए भरोसा नहीं करना चाहिए। इसका मतलब है कि आप अपने पास डीबग करने में मदद करें और कुछ और नहीं।

आपको कंपेलरों की मूल समझ भी लेनी होगी। उदाहरण के लिए, basic blocks और static single assignment form के बारे में जानने की आवश्यकता है। सौभाग्य से वे सीखने या समझने के लिए बहुत मुश्किल अवधारणाएं नहीं हैं (विकिपीडिया लेख पर्याप्त होना चाहिए)।

इससे पहले कि आप कोडिंग शुरू कर सकते हैं, तो आपको पहले तो यहां कुछ पढ़ने क्या करना है पाने के लिए कुछ लिंक है कि आप आरंभ:

  • Architecture Overview: LLVM के एक त्वरित वास्तु सिंहावलोकन। आप इस बारे में एक अच्छा विचार देंगे कि आप किसके साथ काम कर रहे हैं और क्या एलएलवीएम आपके लिए सही उपकरण है।

  • Documentation Head: आप नीचे दिए गए सभी लिंक कहां से पा सकते हैं। अगर मुझे कुछ याद आया तो इसका संदर्भ लें।

  • LLVM's IR reference: यह LLVM आईआर का पूरा विवरण है कि तुम क्या जोड़ तोड़ लिया जाएगा। भाषा अपेक्षाकृत सरल है इसलिए सीखने के लिए बहुत कुछ नहीं है।

  • Programmer's manual: बुनियादी सामान की एक त्वरित अवलोकन आप की आवश्यकता होगी पता करने के लिए जब LLVM साथ काम करना।

  • Writting Passes: सब कुछ आप परिवर्तन या विश्लेषण गुजरता लिखने के लिए पता करने की जरूरत।

  • LLVM Passes: सभी LLVM द्वारा प्रदान की गुजरता है कि आप का उपयोग करना चाहिए और कर सकते हैं की एक व्यापक सूची।ये वास्तव में कोड को साफ करने में मदद कर सकते हैं और विश्लेषण करना आसान बना सकते हैं। उदाहरण के लिए, लूप के साथ काम करते समय, lcssa, simplify-loop और indvar पास आपके जीवन को बचाएंगे।

  • Value Inheritance Tree: यह वैल्यू क्लास के लिए डॉक्सिजन पेज है। यहां महत्वपूर्ण बात यह है कि आईआर संदर्भ पृष्ठ में परिभाषित सभी निर्देशों के लिए दस्तावेज प्राप्त करने के लिए आप विरासत वृक्ष का पालन कर सकते हैं। केवल अजीब राक्षसों को अनदेखा करें जिन्हें वे सहयोग आरेख कहते हैं।

  • Type Inheritance Tree: ऊपर के रूप में लेकिन प्रकार के लिए।

एक बार जब आप यह समझ लेंगे तो यह केक है। मेमोरी एक्सेस खोजने के लिए? store और load निर्देशों के लिए खोजें। उपकरण के लिए? बस Value कक्षा के उचित उप-वर्ग का उपयोग करके आपको जो चाहिए, उसे स्टोर करें और स्टोर के पहले या बाद में डालें। चूंकि आपका प्रश्न थोड़ा अधिक व्यापक है, इसलिए मैं वास्तव में इससे अधिक आपकी सहायता नहीं कर सकता। (नीचे सुधार देखें)

वैसे, मुझे कुछ हफ्ते पहले ऐसा कुछ करना पड़ा। लगभग 2-3 हफ्तों में मैं एलएलवीएम के बारे में जो कुछ भी जरूरी था, उसे सीखने में सक्षम था, एक लूप के भीतर मेमोरी एक्सेस (और अधिक) खोजने के लिए एक विश्लेषण पास बनाते थे और उन्हें बनाए गए एक रूपांतरण पास के साथ उपकरण बनाते थे। इसमें कोई फैंसी एल्गोरिदम शामिल नहीं था (एलएलवीएम द्वारा प्रदान किए गए को छोड़कर) और सब कुछ बहुत सरल था। कहानी का नैतिक यह है कि एलएलवीएम सीखना और काम करना आसान है।


सुधार: जब मैंने कहा कि तुम सब करने की है load और store निर्देश के लिए खोज है कि मैं भूल हो गई है।

load और store निर्देश केवल पॉइंटर्स का उपयोग करके ढेर में किए गए पहुंच प्रदान करेगा। सभी मेमोरी एक्सेस प्राप्त करने के लिए आपको उन मानों को भी देखना होगा जो ढेर पर स्मृति स्थान का प्रतिनिधित्व कर सकते हैं। चाहे स्टैक पर मूल्य लिखा गया हो या रजिस्टर में संग्रहीत किया गया हो, रजिस्टर आवंटन चरण के दौरान निर्धारित किया जाता है जो बैकएंड के अनुकूलन पास में होता है। इसका मतलब है कि यह मंच पर निर्भर है और इस पर भरोसा नहीं किया जाना चाहिए।

अब तक जब तक आप किस प्रकार की मेमोरी एक्सेस की तलाश में हैं, इस बारे में अधिक जानकारी प्रदान करते हैं कि आप किस संदर्भ में हैं और आप उन्हें किस तरह से वाद्य यंत्र करना चाहते हैं, तो मैं आपको और अधिक मदद नहीं कर सकता।

+0

SO पर 25 वें उत्तर के लिए काफी कुछ लिखना! +1 – sehe

+0

@sehe धन्यवाद! जब मैं अपने थीसिस प्रोजेक्ट के कंपाइलर मॉड्यूल पर काम कर रहा था, तो यह बहुत उपयोगी चीजों का एक बड़ा लिंक डंप है :) –

+0

आपके उत्तर के लिए धन्यवाद, –

3

चूंकि दो दिनों के बाद आपके प्रश्न का कोई जवाब नहीं है, इसलिए मैं उसकी पेशकश करूंगा जो थोड़ा सा है लेकिन पूरी तरह से ऑफ-विषय नहीं है।

सी प्रोग्राम के स्थिर विश्लेषण के लिए, एलएलवीएम के विकल्प के रूप में, आप Frama-C प्लग-इन लिखने पर विचार कर सकते हैं।

मौजूदा प्लग-इन जो सी फ़ंक्शन के लिए इनपुट की सूची की गणना करता है, फ़ंक्शन के शरीर में प्रत्येक lvalue पर जाने की आवश्यकता है। यह फ़ाइल src/inout/inputs.ml में लागू किया गया है। कार्यान्वयन छोटा है (जटिलता अन्य प्लग-इन में है जो इसके परिणाम प्रदान करती हैं, जैसे पॉइंटर्स को हल करना) और आपके स्वयं के प्लग-इन के लिए कंकाल के रूप में उपयोग किया जा सकता है।

सार सिंटेक्स ट्री के लिए एक आगंतुक ढांचे द्वारा प्रदान किया जाता है। Lvalues ​​के लिए कुछ विशेष करने के लिए, आप बस इसी विधि को परिभाषित करते हैं।

int a, b, c, d, *p; 

main(){ 
    p = &a; 
    b = c + *p; 
} 

main() की आदानों इस प्रकार गणना:

method vlval lv = ... 

यहाँ आदानों प्लग में क्या करता है की एक उदाहरण है:

आदानों प्लग-इन के दिल विधि परिभाषा है
$ frama-c -input t.c 
... 
[inout] Inputs for function main: 
      a; c; p; 

सामान्य रूप से Frama-C प्लग-इन लिखने के बारे में अधिक जानकारी here मिल सकती है।

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