2008-10-13 13 views
9

पर एक मूल निवासी कैसे करें। .NET Framework के लिए अप्रबंधित API का उपयोग करते समय .NET प्रक्रिया में प्रोफ़ाइल को प्रोफाइल करने के लिए, क्या आईएल निर्देश पॉइंटर को देखना संभव है जो संबंधित है StackSnapshotCallback फ़ंक्शन को प्रदान किया गया मूल निर्देश सूचक?आईएल निर्देश पॉइंटर इन-प्रोसेस

जैसा कि शायद स्पष्ट है, मैं वर्तमान स्टैक का स्नैपशॉट ले रहा हूं, और स्टैक डंप में फ़ाइल और लाइन नंबर की जानकारी प्रदान करना चाहता हूं। प्रबंधित स्टैक एक्सप्लोरर यह ISymUnmanagedMethod::GetSequencePoints से पूछताछ करके करता है। यह बहुत अच्छा है, लेकिन अनुक्रम बिंदु ऑफ़सेट से जुड़े हुए हैं, और मैंने अब तक यह माना है कि ये विधि की शुरुआत (इंटरमीडिएट भाषा में) से ऑफसेट हैं।

अपने ब्लॉग पोस्ट Profiler stack walking: Basics and beyond पर एक फॉलो-अप टिप्पणी में, डेविड ब्रूमन इंगित करता है कि यह मानचित्रण ICorDebugCode::GetILToNativeMapping का उपयोग करके हासिल किया जा सकता है। हालांकि, यह आदर्श नहीं है क्योंकि इस इंटरफ़ेस को किसी अन्य, डीबगर प्रक्रिया से मेरी प्रक्रिया को जोड़ने की आवश्यकता है।

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

कार्यक्षमता संभव है .... आप प्रबंधित कोड के अंदर इच्छा पर एक लाइन-क्रमांकित स्टैक ट्रेस थूक सकते हैं, केवल एक ही सवाल है, यह सुलभ है। इसके अलावा, मैं System::Diagnostics::StackTrace या System::Environment::StackTrace कार्यक्षमता का उपयोग नहीं करना चाहता क्योंकि कारणों से, मुझे स्टैक के वास्तविक डंप में देरी करने की आवश्यकता है .... इसलिए विधि नामों और कोड स्थान के समाधान के लिए लागत को बचाने के लिए वांछनीय है ... देशी और प्रबंधित फ्रेम intermix करने की क्षमता के साथ।

उत्तर

5

आदेश एक देशी अनुदेश सूचक से अनुवाद करने के लिए के रूप में ऑफसेट एक मध्यवर्ती भाषा विधि के लिए ICorProfilerInfo2::DoStackSnapshot द्वारा प्रदान में, आप दो कदम उठाने के बाद से DoStackSnapshot एक आभासी स्मृति पता के रूप में एक FunctionID और देशी अनुदेश सूचक प्रदान करता है चाहिए।

चरण 1, निर्देश सूचक को मूल कोड विधि ऑफ़सेट में परिवर्तित करना है। (जेआईटीएड विधि की शुरुआत से ऑफसेट)। इस के साथ ICorProfilerInfo2::GetCodeInfo2

ULONG32 pcIL(0xffffffff); 
HRESULT hr(E_FAIL); 
COR_PRF_CODE_INFO* codeInfo(NULL); 
COR_DEBUG_IL_TO_NATIVE_MAP* map(NULL); 
ULONG32 cItem(0); 

UINT_PTR nativePCOffset(0xffffffff); 
if (SUCCEEDED(hr = pInfo->GetCodeInfo2(functioId, 0, &cItem, NULL)) && 
    (NULL != (codeInfo = new COR_PRF_CODE_INFO[cItem]))) 
{ 
    if (SUCCEEDED(hr = pInfo->GetCodeInfo2(functionId, cItem, &cItem, codeInfo))) 
    { 
     COR_PRF_CODE_INFO *pCur(codeInfo), *pEnd(codeInfo + cItem); 
     nativePCOffset = 0; 
     for (; pCur < pEnd; pCur++) 
     { 
      // 'ip' is the UINT_PTR passed to the StackSnapshotCallback as named in 
      // the docs I am looking at 
      if ((ip >= pCur->startAddress) && (ip < (pCur->startAddress + pCur->size))) 
      { 
       nativePCOffset += (instructionPtr - pCur->startAddress); 
       break; 
      } 
      else 
      { 
       nativePCOffset += pCur->size; 
      } 

     } 
    } 
    delete[] codeInfo; codeInfo = NULL; 
} 

चरण 2. किया जा सकता है एक बार जब आप एक natvie कोड विधि की शुरुआत से कम करते हैं, तो आप इस का उपयोग एक ICorProfilerInfo2::GetILToNativeMapping का उपयोग कर मध्यवर्ती भाषा विधि की शुरुआत से ऑफसेट करने के लिए कन्वर्ट करने के लिए कर सकते हैं।

if ((nativePCOffset != -1) && 
    SUCCEEDED(hr = pInfo->GetILToNativeMapping(functionId, 0, &cItem, NULL)) && 
    (NULL != (map = new COR_DEBUG_IL_TO_NATIVE_MAP[cItem]))) 
{ 
    if (SUCCEEDED(pInfo->GetILToNativeMapping(functionId, cItem, &cItem, map))) 
    { 
     COR_DEBUG_IL_TO_NATIVE_MAP* mapCurrent = map + (cItem - 1); 
     for (;mapCurrent >= map; mapCurrent--) 
     { 
      if ((mapCurrent->nativeStartOffset <= nativePCOffset) && 
       (mapCurrent->nativeEndOffset > nativePCOffset)) 
      { 
       pcIL = mapCurrent->ilOffset; 
       break; 
      } 
     } 
    } 
    delete[] map; map = NULL; 
} 

यह तो समाधान ढूँढने में दिशा के लिए Mithun Shanbhag के प्रतीक API का उपयोग करके

धन्यवाद एक फ़ाइल और लाइन नंबर करने के लिए कोड स्थान मैप करने के लिए इस्तेमाल किया जा सकता।

+0

यहां छोटी गलती - पहले कोड खंड के लाइन 17 में frame.pc "instructPtr" होना चाहिए, जो आपके DoStackSnapshot कॉलबैक का UINT_PTR आईपी पैरामीटर है। धन्यवाद एक गुच्छा स्टीवन! आपने वास्तव में मेरी मदद की :) –

+0

एचआरएम ... अच्छा बिंदु। मुझे याद नहीं है कि frame.pc कहाँ से आया था। शायद मैं यह स्पष्ट करने की कोशिश कर रहा था कि क्या इस्तेमाल किया जा रहा था। किसी भी मामले में, जहां से यह आता है, इस बारे में एक टिप्पणी के साथ वास्तविक मूल्य समझदार लगता है। संपादित। सूचक के लिए धन्यवाद। – Steven

0
Console.WriteLine("StackTrace: '{0}'", Environment.StackTrace); 

सुनिश्चित करें कि आपका निर्माण प्रतीक उत्पन्न करता है।

चर्चा पर विस्तार:

के रूप में शायद स्पष्ट है, मैं वर्तमान ढेर का एक स्नैपशॉट ले रहा हूँ, और ढेर डंप में फ़ाइल और लाइन नंबर की जानकारी प्रदान करना चाहते हैं।

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

ज्यादातर लोग आम तौर पर पूछते हैं "आप वास्तव में क्या करने की कोशिश कर रहे हैं?" चीजों को करने के एक बेहद जटिल तरीके के जवाब के रूप में। में मामलों में एक आसान/आसान तरीका है। देशी कोड के लिए एक स्टैक ट्रेसर लिखने के बाद, मुझे पता है कि यह गन्दा हो सकता है।

अब शायद आप सबकुछ काम कर सकते हैं, तो - बस मेरा $।02

+0

सुझाव के लिए धन्यवाद, लेकिन सवाल बताता है कि मैं प्रतीकों के संकल्प में देरी करना चाहता हूं और अप्रबंधित फ्रेम को हल करने में सक्षम होना चाहता हूं। यह दृष्टिकोण या तो आवश्यकता को पूरा नहीं करता है। मैंने प्रश्न को और अधिक स्पष्ट होने के लिए संपादित किया है। – Steven

+0

यदि आप इसे डीबगर में चला रहे हैं, तो संभावना है कि 'कॉल स्टैक' विंडो पहले ही प्रतीकों को हल कर रही है। अप्रबंधित फ्रेम - आईएमओ देशी ढेर पहले से ही बहुत अच्छी तरह परिभाषित है और ऐसा करने के लिए पहले ही Win32 API फ़ंक्शन मौजूद हैं। जैसे StackWalk64, SymGetLineFromAddr64 और SymGetModuleBase64। –

+0

मैं मिश्रित मोड स्टैक्स प्रदर्शित करने के लिए एक रिसाव-पहचान उपकरण संशोधित कर रहा हूं और वास्तव में सभी ढेर को हल नहीं करना चाहता हूं। बस जो लीक की ओर ले जाते हैं। मैं हर आवंटन पर डीबगर में तोड़ना नहीं चाहता हूं। और dbghlp फ़ंक्शंस आप केवल शुद्ध देशी ढेर पर काम करते हैं। – Steven

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