2012-02-10 15 views
30

से xxd की तरह स्वरूपित मेमोरी डंप मैं एक बफर का निरीक्षण करने की कोशिश कर रहा हूं जिसमें बाइनरी स्वरूपित संदेश है, लेकिन इसमें स्ट्रिंग डेटा भी शामिल है। एक उदाहरण के रूप में, मैं इस सी कोड का उपयोग कर रहा:जीडीबी

int main (void) { 
    char buf[100] = "\x01\x02\x03\x04String Data\xAA\xBB\xCC"; 

    return 0; 
} 

मैं (क्या, buf में है एक प्रारूप xxd के लिए इसी तरह की की एक हेक्स डंप प्राप्त करना चाहते हैं, तो उसके एक सटीक मिलान है मुझे परवाह नहीं है , जो मैं वास्तव में देख रहा हूं वह प्रिंट करने योग्य वर्णों के साथ एक हेक्स डंप पक्ष है)।

GDB के अंदर मैं की तरह कुछ का उपयोग कर सकते हैं:

(gdb) x /100bx buf 
0x7fffffffdf00: 0x01 0x02 0x03 0x04 0x53 0x74 0x72 0x69 
0x7fffffffdf08: 0x6e 0x67 0x20 0x44 0x61 0x74 0x61 0xaa 
0x7fffffffdf10: 0xbb 0xcc 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf18: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf20: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf28: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf30: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf38: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf40: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf48: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf50: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf58: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 

जो ठीक है, लेकिन इसे उस तरह से तार बाहर लेने के लिए मुश्किल है ... या मैं

(gdb) x /100bs buf 
0x7fffffffdf00: "\001\002\003\004String Data\252\273\314" 
0x7fffffffdf13: "" 
0x7fffffffdf14: "" 
0x7fffffffdf15: "" 
0x7fffffffdf16: "" 
0x7fffffffdf17: "" 
... 

जो यह मुश्किल बना देता है का उपयोग कर सकते बाइनरी भाग को पढ़ने के लिए ... जिन वास्तविक संदेशों के साथ मैं काम कर रहा हूं उनमें बहुत से एसीसी नूल हैं, वास्तव में, यह वास्तव में एक गड़बड़ की तरह दिखता है।

सबसे अच्छा मैं के साथ आ सकते हैं यह करने के लिए है:

(gdb) dump binary memory dump.bin buf buf+100 

और फिर

$ xxd dump.bin 
0000000: 0102 0304 5374 7269 6e67 2044 6174 61aa ....String Data. 
0000010: bbcc 0000 0000 0000 0000 0000 0000 0000 ................ 
0000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 
0000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 
0000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 
0000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 
0000060: 0000 0000        .... 

लेकिन यह है कि हर बार ऐसा करने के लिए एक दर्द है। मैंने किसी को यह समझ लिया कि वहां पहले यह चाहता था, तो सोच रहा है कि किसी को जीडीबी के अंदर ऐसा करने का कोई तरीका मिला है। इसके अलावा आप इस तरह मूल स्मृति से पते खो देते हैं।

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

उत्तर

52
(gdb) define xxd 
>dump binary memory dump.bin $arg0 $arg0+$arg1 
>shell xxd dump.bin 
>end 
(gdb) xxd &j 10 
0000000: 0000 0000 0000 0000 0000 0000 4d8c a7f7 ............M... 
0000010: ff7f 0000 0000 0000 0000 0000 c8d7 ffff ................ 
0000020: ff7f 0000 0000 0000 

आसान पर्याप्त ;-)

आप संभावना Python स्क्रिप्ट (आधुनिक GDB संस्करणों अजगर दुभाषिया एम्बेडेड है) लिख सकता है ऐसा ही करने के लिए, और "बाहर खोल" की जरूरत से छुटकारा पाने लगता है।

+0

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

+0

ध्यान दें कि यदि '$ arg0' किसी संरचना के लिए सूचक है, तो '$ arg1' को ऑब्जेक्ट्स की गिनती के रूप में माना जाएगा, बाइट्स नहीं। '((शून्य *) $ arg0) + $ arg0 + $ arg1' के बजाय + $ arg1' का उपयोग करें यदि यह एक समस्या होगी। –

+0

यह भी ध्यान रखें कि 'xxd' के नए संस्करण' -o' ध्वज का समर्थन करते हैं, जो प्रदर्शित पते मानों में ऑफसेट जोड़ता है। –

23

तो, मैं अजगर इंटरफेस के साथ प्रयोग करना समाप्त हो गया है और इस के साथ आया था:

import gdb 
from curses.ascii import isgraph 

def groups_of(iterable, size, first=0): 
    first = first if first != 0 else size 
    chunk, iterable = iterable[:first], iterable[first:] 
    while chunk: 
     yield chunk 
     chunk, iterable = iterable[:size], iterable[size:] 

class HexDump(gdb.Command): 
    def __init__(self): 
     super (HexDump, self).__init__ ('hex-dump', gdb.COMMAND_DATA) 

    def invoke(self, arg, from_tty): 
     argv = gdb.string_to_argv(arg) 
     if len(argv) != 2: 
      raise gdb.GdbError('hex-dump takes exactly 2 arguments.') 
     addr = gdb.parse_and_eval(argv[0]).cast(
      gdb.lookup_type('void').pointer()) 
     try: 
      bytes = int(gdb.parse_and_eval(argv[1])) 
     except ValueError: 
      raise gdb.GdbError('Byte count numst be an integer value.') 

     inferior = gdb.selected_inferior() 

     align = gdb.parameter('hex-dump-align') 
     width = gdb.parameter('hex-dump-width') 
     if width == 0: 
      width = 16 

     mem = inferior.read_memory(addr, bytes) 
     pr_addr = int(str(addr), 16) 
     pr_offset = width 

     if align: 
      pr_offset = width - (pr_addr % width) 
      pr_addr -= pr_addr % width 

     for group in groups_of(mem, width, pr_offset): 
      print '0x%x: ' % (pr_addr,) + ' '*(width - pr_offset), 
      print ' '.join(['%02X' % (ord(g),) for g in group]) + \ 
       ' ' * (width - len(group) if pr_offset == width else 0) + ' ', 
      print ' '*(width - pr_offset) + ''.join(
       [g if isgraph(g) or g == ' ' else '.' for g in group]) 
      pr_addr += width 
      pr_offset = width 

class HexDumpAlign(gdb.Parameter): 
    def __init__(self): 
     super (HexDumpAlign, self).__init__('hex-dump-align', 
              gdb.COMMAND_DATA, 
              gdb.PARAM_BOOLEAN) 

    set_doc = 'Determines if hex-dump always starts at an "aligned" address (see hex-dump-width' 
    show_doc = 'Hex dump alignment is currently' 

class HexDumpWidth(gdb.Parameter): 
    def __init__(self): 
     super (HexDumpWidth, self).__init__('hex-dump-width', 
              gdb.COMMAND_DATA, 
              gdb.PARAM_INTEGER) 

    set_doc = 'Set the number of bytes per line of hex-dump' 

    show_doc = 'The number of bytes per line in hex-dump is' 

HexDump() 
HexDumpAlign() 
HexDumpWidth() 

मुझे पता है यह सबसे सुंदर और सुरुचिपूर्ण समाधान नहीं हो सकता है, लेकिन यह काम किया और रूप में काम करता हो जाता है पहला ड्राफ्ट यह ~/.gdbinit की तरह में शामिल किया जा सकता है:

python 
sys.path.insert(0, '/path/to/module/dir') 
import hexdump 
end 

तो उपरोक्त कार्यक्रम के साथ इस्तेमाल किया जा सकता है ताकि तरह:

(gdb) hex-dump buf 100 
0x7fffffffdf00: 01 02 03 04 53 74 72 69 6E 67 20 44 61 74 61 AA ....String Data. 
0x7fffffffdf10: BB CC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf60: 00 00 00 00          .... 

और अच्छा उपाय कुछ अन्य छूता:

(gdb) set hex-dump-align on 
Determines if hex-dump always starts at an "aligned" address (see hex-dump-width 
(gdb) hex-dump &buf[5] 95 
0x7fffffffdf00:     74 72 69 6E 67 20 44 61 74 61 AA  tring Data. 
0x7fffffffdf10: BB CC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf60: 00 00 00 00          .... 

(gdb) set hex-dump-width 8 
Set the number of bytes per line of hex-dump 
(gdb) hex-dump &buf[5] 95 
0x7fffffffdf00:     74 72 69  tri 
0x7fffffffdf08: 6E 67 20 44 61 74 61 AA ng Data. 
0x7fffffffdf10: BB CC 00 00 00 00 00 00 ........ 
0x7fffffffdf18: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf20: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf28: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf30: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf38: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf40: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf48: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf50: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf58: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf60: 00 00 00 00    .... 

नहीं वादा करता है कि बग नहीं हैं :)। यदि लोग रुचि रखते हैं तो मैं इसे गिटूब या कुछ में रख सकता हूं।

मैंने केवल जीडीबी 7.4 के साथ इसका परीक्षण किया है।

+1

+1 इस समाधान के बाद से मूल पता, बहुत आसान है! –

+0

मुझे एक 'ImportError: हेक्सडंप नामक कोई मॉड्यूल नहीं मिला है – haneefmubarak

+0

सुनिश्चित करें कि आपने स्क्रिप्ट को hexdump.py के रूप में सहेजा है और यह कि आपके .gdbinit में पथ सही है – FatalError

2

एक अनुकूलित उपयोगकर्ता FatalError के समाधान के

  • लंबाई पैरामीटर वैकल्पिक
  • नाम दिया HD को

    • अजगर के साथ काम करता है 3
    • एक हेक्स-कॉल-हैडर जोड़ा संस्करण

    उदाहरण

    hd 0xbfffe4f1

    hd 0xbfffe4f1 500

    import gdb 
    from curses.ascii import isgraph 
    
    def groups_of(iterable, size, first=0): 
        first = first if first != 0 else size 
        chunk, iterable = iterable[:first], iterable[first:] 
        while chunk: 
         yield chunk 
         chunk, iterable = iterable[:size], iterable[size:] 
    
    class HexDump(gdb.Command): 
        def __init__(self): 
         super (HexDump, self).__init__ ('hd', gdb.COMMAND_DATA) 
    
        def invoke(self, arg, from_tty): 
         argv = gdb.string_to_argv(arg) 
    
         addr = gdb.parse_and_eval(argv[0]).cast(
          gdb.lookup_type('void').pointer()) 
         if len(argv) == 2: 
          try: 
           bytes = int(gdb.parse_and_eval(argv[1])) 
          except ValueError: 
           raise gdb.GdbError('Byte count numst be an integer value.') 
         else: 
          bytes = 500 
    
         inferior = gdb.selected_inferior() 
    
         align = gdb.parameter('hex-dump-align') 
         width = gdb.parameter('hex-dump-width') 
         if width == 0: 
          width = 16 
    
         mem = inferior.read_memory(addr, bytes) 
         pr_addr = int(str(addr), 16) 
         pr_offset = width 
    
         if align: 
          pr_offset = width - (pr_addr % width) 
          pr_addr -= pr_addr % width 
         start=(pr_addr) & 0xff; 
    
    
         print ('   ' , end="") 
         print (' '.join(['%01X' % (i&0x0f,) for i in range(start,start+width)]) , end="") 
         print (' ' , end="")  
         print (' '.join(['%01X' % (i&0x0f,) for i in range(start,start+width)])) 
    
         for group in groups_of(mem, width, pr_offset): 
          print ('0x%x: ' % (pr_addr,) + ' '*(width - pr_offset), end="") 
          print (' '.join(['%02X' % (ord(g),) for g in group]) + \ 
           ' ' * (width - len(group) if pr_offset == width else 0) + ' ', end="")  
          print (' '*(width - pr_offset) + ' '.join(
           [chr(int.from_bytes(g, byteorder='big')) if isgraph(int.from_bytes(g, byteorder='big') ) or g == ' ' else '.' for g in group])) 
          pr_addr += width 
          pr_offset = width 
    
    class HexDumpAlign(gdb.Parameter): 
        def __init__(self): 
         super (HexDumpAlign, self).__init__('hex-dump-align', 
                  gdb.COMMAND_DATA, 
                  gdb.PARAM_BOOLEAN) 
    
        set_doc = 'Determines if hex-dump always starts at an "aligned" address (see hex-dump-width' 
        show_doc = 'Hex dump alignment is currently' 
    
    class HexDumpWidth(gdb.Parameter): 
        def __init__(self): 
         super (HexDumpWidth, self).__init__('hex-dump-width', 
                  gdb.COMMAND_DATA, 
                  gdb.PARAM_INTEGER) 
    
        set_doc = 'Set the number of bytes per line of hex-dump' 
    
        show_doc = 'The number of bytes per line in hex-dump is' 
    
    HexDump() 
    HexDumpAlign() 
    HexDumpWidth() 
    
  • 1

    दुर्भाग्य से, @ FatalError की और @ gunthor के संस्करणों मेरे लिए काम नहीं किया है, इसलिए मैं एक और एक अभी तक अपने आप को लिखा था। यह है कि यह कैसे की तरह लग रहा है: xxd की

    (gdb) xxd hello_string 0xc 
    00000001_00000f87:     48 656c 6c6f 0957 6f72   Hello.Wor 
    00000001_00000f90: 6c64 0a         ld. 
    

    नए संस्करणों -o फ़्लैग को निर्दिष्ट करने की अनुमति देता है कि एक दिखाया गया है एक (जो हमेशा 0000000 पर शुरू कर देंगे) में जोड़ने के लिए ऑफसेट का समर्थन करता है।

    xxd -o उपलब्ध नहीं है, तो यहां एक विकल्प है जो xxd 'डी के स्थान का सही ढंग से संरेखित और पता दिखाता है।

    xxd आदेश:

    define xxd 
        dump binary memory /tmp/dump.bin $arg0 $arg0+$arg1 
        eval "shell xxd-o %p /tmp/dump.bin", $arg0 
    end 
    

    यकीनन बदसूरत पर्ल स्क्रिप्ट xxd-o (ऑफसेट के साथ xxd):

    #!/usr/bin/env perl 
    use IPC::Open2; 
    $SIG{'__WARN__'} = sub{ die "$0: $!\n" }; 
    
    my $offset = shift // "0"; 
    $offset = oct($offset) if $offset =~ /^0/; 
    my $base = $offset >= 2**32 ? 16 : 8; 
    
    my $zeroes = $offset % 16; 
    my $padding = 1 + int($zeroes/2) + 2*$zeroes; 
    my $bytestr = "\0" x $zeroes; 
    { local $/; $bytestr .= <> } 
    
    open2(\*XXD_OUT, \*XXD_IN, "xxd") or die "xxd is not available!"; 
    print XXD_IN $bytestr; close XXD_IN; 
    
    if ($zeroes) { 
        $_ = <XXD_OUT>; 
        s/^(.{50}).{$zeroes}/$1 . (' ' x $zeroes)/ge; 
        s/^([[:xdigit:]]+:).{$padding}/$1 . (' ' x $padding)/ge; 
        my $newoff = sprintf("%0${base}x",hex($1)+$offset) =~ s/^(.{8})(.{8})$/$1_$2/r; 
        s/^([[:xdigit:]]+):/$newoff:/g; 
        print 
    } 
    while (<XXD_OUT>) { 
        s/^([[:xdigit:]]+)(?=:)/sprintf("%0${base}x", hex($1)+$offset-$offset%16) =~ s[^(.{8})(.{8})$][$1_$2]r/ge; 
        print 
    } 
    

    सुधार स्वागत करते हैं! :-)

    +0

    'xxd -o' पर: https://stackoverflow.com/q/10233526/8446 –