Search code examples
lldb

lldb: Displaying array as hex


In lldb is it possible to display a uint8_t array of bytes in a concatenated hex?

For instance the default behaviour for displaying the uint256 type described here is

{
  [14] = '['
  [15] = '\xbf'
  [16] = '('
  [17] = '\xc3'
  [18] = 'O'
  [19] = ':'
  [20] = '^'
  [21] = '3'
  [22] = '*'
  [23] = '\x1f'
  [24] = '\xc7'
  [25] = '\xb2'
  [26] = '\xb7'
  [27] = '<'
  [28] = '\xf1'
  [29] = '\x88'
  [30] = '\x91'
  [31] = '\x0f'
}

by running type summary add --summary-string "${var.data[0-31]%x}" uint256 I can display it like this:

[0x06,0x22,0x6e,0x46,0x11,0x1a,0x0b,0x59,0xca,0xaf,0x12,0x60,0x43,0xeb,0x5b,0xbf,0x28,0xc3,0x4f,0x3a,0x5e,0x33,0x2a,0x1f,0xc7,0xb2,0xb7,0x3c,0xf1,0x88,0x91,0x0f]

but I wanted something like this:

0x06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f

Solution

  • I can't think of a way to do this with the summary string formatters. We do some special purpose magic like this for char[] but that's behind the %s specifier which you don't want.

    However, it is fairly easy to write a python summary to do this. Here's a simple example for the type uint8_t [32]:

    def unvector_32 (valobj,internal_dict):
        str = "0x" 
        for i in range(0,31): 
             str += ("%x"%(valobj.GetChildAtIndex(i).GetValueAsUnsigned())).zfill(2) 
        return str
    
    def __lldb_init_module(debugger, internal_dict):
        debugger.HandleCommand('type category define -e my_formatters')
        debugger.HandleCommand('type summary add -w my_formatters -F %s.unvector_32 "uint8_t [32]" -v'%(__name__))
    

    Put that in a .py file somewhere (I put all these in ~/.lldb) and do:

    (lldb) com scr imp ~/.lldb/my_formatters.py
    

    either in your lldb session or in your ~/.lldbinit. Then you will see:

    (lldb) fr v data
    (uint8_t [32]) data = 0x01020304050600000000000000000000000000000000000000000000000000
    (lldb)
    

    I think that's roughly the output you wanted. To apply this to the uint256 class you can change the match type to "uint256" when you add the summary, and have the summary function first get the data member using GetChildMemberWithName("data") then print the individual vector elements. You could also use a regex match against uint([0-9]+) and then get the number of elements in data with the GetNumChildren call if you want the formatter to be more general...

    BTW, I find it handy to put all my formatters in a category so I can list them easily (type summary list -w my_formatters) and turn them all off easily if I've messed something up...

    More on the SB API's is here:

    http://lldb.llvm.org/python_reference/index.html