2009-10-08 6 views
18

मैं जानना चाहता हूं कि विशाल एप्लिकेशन के अंदर एक निश्चित संदेश मुद्रित किया गया है। एप्लिकेशन इतना बड़ा और पुराना है कि यह टर्मिनल को टेक्स्ट प्रिंट करने के सभी कल्पनीय तरीकों का उपयोग करता है; उदाहरण के लिए printf(), fprintf (stdout, ...) आदिजीडीबी में "टर्मिनल पर कुछ मुद्रित" पर ब्रेकपॉइंट कैसे लगाया जा सकता है?

मैं लिखने() सिस्टम कॉल पर ब्रेकपॉइंट लिखने के लिए लिखता हूं लेकिन फिर मुझे विभिन्न फ़ाइल I/के कारण बहुत सारे ब्रेकपॉइंट स्टॉप के साथ बाढ़ आती है I/हे ऑपरेशंस जो लिखते हैं() भी।

तो मूल रूप से मैं प्रोग्राम को कुछ भी प्रिंट करता हूं जब भी प्रोग्राम टर्मिनल पर कुछ प्रिंट करता है लेकिन साथ ही मैं प्रोग्राम को कुछ लिखने पर जीडीबी को रोकना नहीं चाहता हूं।

+1

भी देखें [मैं कैसे निगरानी कर सकते हैं क्या में डाल दिया जा रहा है पाइप में एक विशिष्ट स्ट्रिंग जमा होने पर मानक आउट बफर और ब्रेक?] (http://stackoverflow.com/questions/8235436/how-can-i-monitor-whats-being-put-into-the- मानक- आउट-बफर-एंड-ब्रेक-ए-ए) –

+0

क्या आप टर्मिनल में दिखाई देने वाले "कुछ" के लिए स्रोत को 'grep' नहीं कर सकते हैं, फिर वहां ब्रेकपॉइंट रखें? – Calmarius

उत्तर

18

एक सशर्त ब्रेकपॉइंट का उपयोग करें जो पहले पैरामीटर की जांच करता है। 64-बिट x86 सिस्टम पर शर्त होगा:

अगर (gdb) ख लिखने 1 == $ RDI

32-बिट सिस्टम पर, यह अधिक जटिल है क्योंकि पैरामीटर ढेर पर है, जिसका अर्थ है कि आपको एक int * के लिए $ esp डालना होगा और fd पैरामीटर को इंडेक्स करना होगा। उस बिंदु पर ढेर में वापसी का पता, लंबाई, बफर और अंततः एफडी है।

यह हार्डवेयर प्लेटफ़ॉर्म के बीच बहुत भिन्न होता है।

+1

मैं इसके साथ थोड़ा सा गड़बड़ करता हूं और पाया कि एफडी संख्या "* (int) ($ esp + 4)" और स्ट्रिंग लंबाई "(int) * (int) ($ esp + 12)" के रूप में उपलब्ध है और आखिरकार स्ट्रिंग डेटा "* (int) ($ esp + 8)" के रूप में। तो आप की तरह कुछ कर सकते हैं STDOUT के लिए: तोड़ने लिखने अगर 1 == * (int) ($ esp 4) आदेश प्रिंट (int) * (int) ($ esp + 12) एक्स/s * (int) ($ esp + 8) अंत लेकिन जब मैंने इसे _huge_ एप्लिकेशन पर अभ्यास में उपयोग करने का प्रयास किया तो यह पता चला कि यह विधि मूर्खतापूर्ण नहीं है क्योंकि यह रीडायरेक्ट आदि को संभाल नहीं पाती है, इसलिए यदि ऐप डुप्लिकेट का उपयोग करता है() stdout पर आप stdout पर मुद्रित कुछ सामान याद कर सकते हैं। – martin

+0

यहां थोड़ा और परिष्कृत प्रयास है:

 break write commands silent if !isatty(*(int)($esp + 4)) c end echo \ntty write(), size: x/d (int)($esp + 12) echo tty write(), data: x/s *(int)($esp + 8) end 
martin

11

gdb 7.0 के साथ, आप syscall लिखने() पर सशर्त ब्रेकप्वाइंट सेट कर सकते हैं:

(gdb) catch syscall write 
Catchpoint 1 (syscall 'write' [4]) 
(gdb) condition 1 $ebx==1 

$ EBX पहले syscall पैरामीटर है - एफडी यहाँ संख्या

+0

नोट: 'printf' buffered है, इसलिए ऐसा हो सकता है कि आप केवल दूसरे 'printf' कॉल पर पहले' printf' के लिए 'लिखने' को देखते हैं। –

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