gdb

2012-01-12 22 views
9

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

क्या मैं प्राप्त करने के लिए आशा करती हूं कि कुछ इस तरह है:

(gdb) /* some command */ 
0x2818a7c0: push %ebp 
0x2818a7c1: mov %esp,%ebp 
0x2818a7c3: push %ebx 
0x2818a7c4: sub $0x4,%esp 
... 
0x28563622: mov %esi,0x0(%eax) 
Program received signal SIGSEGV, Segmentation fault. 

क्या मैं कर रहा हूँ, प्रोग्राम काउंटर के लिए एक प्रदर्शन की स्थापना इसलिए की तरह है:

(gdb) display/i $pc 

और तो stepi साथ कोड के माध्यम से चल:

(gdb) stepi 
1: x/i $pc 0x2818a7c0: push %ebp 

हालांकि, दुर्घटना सैकड़ों या टी है निर्देशों के हजारों दूर, और मैं कई बार एक बार "प्रवेश" करने के बिना, प्रत्येक को एक साथ (एक साथ, अगर बेहतर) देखने का एक तरीका चाहूंगा। इसके अलावा, अगर मैं इसे मैन्युअल रूप से करना चाहता था, तो मुझे प्रत्येक निर्देश के बीच (gdb) प्रॉम्प्ट दिखाई देगा, जो वांछनीय से कम है।

एक मार्ग मैं संक्षिप्त देखा है scripting है, लेकिन मेरे ही सोचा, main() पर सेटअप करने के लिए है यह प्रदर्शित करते हैं और एक अन्य को तोड़ने (अगले निर्देश के लिए), और फिर जारी रखने के लिए, लेकिन फिर मैं commands उपयोग नहीं कर सकते commands ब्लॉक के भीतर, इसलिए यह जिस तरह से मैं कल्पना कर रहा हूं, वह काम नहीं करेगा।

यदि यह महत्वपूर्ण है, तो मैं फ्रीबीएसडी पर काम कर रहा हूं।

उत्तर

13

निम्नलिखित आप क्या पूछा के लिए क्या करना चाहिए:

# not strictly required, but you'll likely want the log anyway 
(gdb) set logging on 

# ask gdb to not stop every screen-full 
(gdb) set height 0 

(gdb) while 1 
> x/i $pc 
> stepi 
> end 

हालांकि, डिबगिंग के लिए इस दृष्टिकोण की संभावना व्यर्थ साबित होगा: बस कर रहे हैं बहुत अधिक निर्देशों को यहां तक ​​कि सबसे छोटे कार्यक्रमों में भी निष्पादित किया गया।

क्रैश तक प्रोग्राम चलाने के लिए एक बेहतर तरीका हो सकता है, यह समझने का प्रयास करें कि वर्तमान कार्य क्या कर रहा है और कौन इसे कॉल करता है, और उचित रूप से ब्रेकपॉइंट्स सेट करता है।

x86 पर, आप अक्सर पूरी तरह से छीनने वाले निष्पादन योग्य में फ़ंक्शन सीमाओं को कम कर सकते हैं।

एक और चीज जिसे आप देखना चाहते हैं strace/truss आउटपुट है, ताकि आप देख सकें कि क्रैश पॉइंट से पहले कौन सी सिस्टम कॉल तुरंत होती है।

0
  1. Dissassemble द्विआधारी अलग से (जैसे objdump प्रयोग करके) और सूची से परामर्श करते हुए
  2. उपयोग IDA और उसके डिबगर डिबगिंग। आईएमओ का बेहतर अनुभव

(अस्वीकरण: मैं हेक्स-रे के लिए काम करते हैं)

+0

मैंने अपना प्रश्न यह अद्यतन करने के लिए अद्यतन किया है कि मैं वर्तमान में फ्रीबीएसडी पर काम कर रहा हूं, जिसका मेरा मानना ​​है कि नियम # 2 है? –

+0

आह हाँ, वर्तमान में आईडीए डीबीगिंग फ्रीबीएसडी बाइनरी का समर्थन नहीं करता है। हालांकि, आप अभी भी इसे डिस्सेबलर (विंडोज/वाइन या फ्रीबीएसडी पर लिनक्स सपोर्ट का उपयोग करके) के रूप में उपयोग कर सकते हैं - यह मृत सूची को देखने से कहीं ज्यादा बेहतर है। –

1

अजगर पटकथा

यह आपके पागल विचारों को प्राप्त करने के GDB पटकथा तुलना में अधिक लचीलापन दे देंगे।

मुख्य समस्या यहाँ, बस GDB स्क्रिप्ट के साथ की तरह, कि यह संभवत लक्ष्य हार्डवेयर समर्थन के बिना सबसे अनुप्रयोगों के लिए बहुत धीमी गति से हो जाएगा, जैसे: एक सी हैलो दुनिया 2 मिनट केवल 60k main से शुरू बस जाने के लिए निर्देश के लिए ले जाता है puts से अधिक और अंतिम रूप दें।

class TraceAsm(gdb.Command): 
    def __init__(self): 
     super().__init__(
      'trace-asm', 
      gdb.COMMAND_BREAKPOINTS, 
      gdb.COMPLETE_NONE, 
      False 
     ) 
    def invoke(self, argument, from_tty): 
     argv = gdb.string_to_argv(argument) 
     if argv: 
      gdb.write('Does not take any arguments.\n') 
     else: 
      done = False 
      thread = gdb.inferiors()[0].threads()[0] 
      last_path = None 
      last_line = None 
      with open('trace.tmp', 'w') as f: 
       while thread.is_valid(): 
        frame = gdb.selected_frame() 
        sal = frame.find_sal() 
        symtab = sal.symtab 
        if symtab: 
         path = symtab.fullname() 
         line = sal.line 
        else: 
         path = None 
         line = None 
        if path != last_path: 
         f.write("path {}{}".format(path, os.linesep)) 
         last_path = path 
        if line != last_line: 
         f.write("line {}{}".format(line, os.linesep)) 
         last_line = line 
        pc = frame.pc() 
        f.write("{} {} {}".format(hex(pc), frame.architecture().disassemble(pc)[0]['asm'], os.linesep)) 
        gdb.execute('si', to_string=True) 
TraceAsm() 

नमूना उत्पादन:

path /home/cirsan01/bak/git/cpp-cheat/c/exit.c 
line 95 
0x7ffff7318f9b add $0x8,%rbp 
0x7ffff7318f9f cmp %r12,%rbp 
0x7ffff7318fa2 jb  0x7ffff7318f98 <__run_exit_handlers+136> 
line 97 
0x7ffff7318fa4 mov %ebx,%edi 
0x7ffff7318fa6 callq 0x7ffff73ab710 <__GI__exit> 
path /build/glibc-bfm8X4/glibc-2.23/posix/../sysdeps/unix/sysv/linux/_exit.c 
line 27 
0x7ffff73ab710 movslq %edi,%rdx 
0x7ffff73ab713 mov 0x2f775e(%rip),%r9  # 0x7ffff76a2e78 
line 31 
0x7ffff73ab71a mov $0xe7,%r8d 
line 33 
0x7ffff73ab720 mov $0x3c,%esi 
0x7ffff73ab725 jmp 0x7ffff73ab740 <__GI__exit+48> 
line 31 
0x7ffff73ab740 mov %rdx,%rdi 
0x7ffff73ab743 mov %r8d,%eax 
0x7ffff73ab746 syscall 

उबंटू 16.04, GDB 7.11 परीक्षण में। GitHub upstream

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