(gdb) p/t table->read_set->bitmap[0] @ (table->read_set->n_bits+7)/8
gdb.Value
). And the class has a to_string()
method, which, in fact, returns what we want to see. For example: class BitmapPrinter: def __init__(self, val): self.val = val def to_string(self): s='' for i in range((self.val['n_bits']+7)//8): s = format(int(self.val['bitmap'][i]), '032b') + s return "b'" + s[-int(self.val['n_bits']):] + "'" class StringPrinter: def __init__(self, val): self.val = val def to_string(self): return '_' + self.val['str_charset']['name'].string() + \ ' "' + self.val['Ptr'].string('ascii', 'strict', self.val['str_length']) + '"'
gdb.Value
and decides whether to use our class. For simplicity, the gdb.printing
module has a ready-made implementation that uses regular expressions, something like this: import gdb.printing def build_pretty_printer(): pp = gdb.printing.RegexpCollectionPrettyPrinter( "my_library") pp.add_printer('String', '^String$', StringPrinter) pp.add_printer('bitmap', '^st_bitmap$', BitmapPrinter) return pp gdb.printing.register_pretty_printer( gdb.current_objfile(), my_library.build_pretty_printer()
pp.add_printer()
is the name, regular for the type, and the class that this type prints.to_string()
, everything else will be copied from class to class. The printer registration code is also a bit too much, even the type name is repeated three times in a row. (gdb) p opt_tc_log_file $2 = 0x555556204273 "tc.log" (gdb) p table->field[0] $3 = (Field_varstring *) 0x555557437a88
StringPtrPrinter
and BitmapPtrPrinter
, which have to_string()
almost the same, but also displays the address. And you can expand already written ones by adding both there and there checks, so that they catch them on the fly, when val
is a pointer, and the address is typed accordingly. One way or another, copy and copy. The same code from class to class. I quickly got tired of it, and I began to simplify everything. Ideally, I wanted to write these printers like this: @PrettyPrinter def String(val): return '_' + val['str_charset']['name'].string() + \ ' "' + val['Ptr'].string('ascii', 'strict', val['str_length']) + '"' @PrettyPrinter def st_bitmap(val): s='' for i in range((val['n_bits']+7)//8): s = format(int(val['bitmap'][i]), '032b') + s return "b'" + s[-int(val['n_bits']):] + "'"
gdb.printing
agreed, but it turned out that the wrapper is sitting on the wrapper and the wrapper is chasing. import gdb.printing def PrettyPrinter(arg): name = getattr(arg, '__name__', arg) def PrettyPrinterWrapperWrapperWrapper(func): class PrettyPrinterWrapperWrapper: class PrettyPrinterWrapper: def __init__(self, prefix, val, cb): self.prefix = prefix self.val = val self.cb = cb def to_string(self): return self.prefix + self.cb(self.val) def __init__(self, name, cb): self.name = name self.enabled = True self.cb = cb def __call__(self, val): prefix = '' if val.type.code == gdb.TYPE_CODE_PTR: prefix = '({}) {:#08x} '.format(str(val.type), long(val)) try: val = val.dereference() except: return None valtype = val.type.unqualified() if valtype.name == self.name: return self.PrettyPrinterWrapper(prefix, val, self.cb) if valtype.strip_typedefs().name == self.name: return self.PrettyPrinterWrapper(prefix, val, self.cb) return None pp = PrettyPrinterWrapperWrapper(name, func) gdb.printing.register_pretty_printer(None, pp, True) return func if callable(arg): return PrettyPrinterWrapperWrapperWrapper(arg) return PrettyPrinterWrapperWrapperWrapper
gdb.Value
value are both passed to the constructor of the PrettyPrinterWrapper
class. And by to_string()
it calls this function with this value.gdb.printing.RegexpCollectionPrettyPrinter
, but I do not want it, so I have my own class, with poker and courtesans. It automatically determines when the value is a pointer, and outputs (Typename *) address
. And then it creates and returns the corresponding PrettyPrinterWrapper. And supports typedefs. It is called, of course, PrettyPrinterWrapperWrapper. Then I thought it was funny.Alter_inplace_info::HA_ALTER_FLAGS
, the function was not created in python, so I had to make the decorator accept the name of the type as an argument: @PrettyPrinter('Alter_inplace_info::HA_ALTER_FLAGS') def HA_ALTER_FLAGS(val): s='' ...
@PrettyPrinter def sql_mode_t(val): s='' modes=['STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH'] for i in range(0,len(modes)): if val & (1 << i): s += ',' + modes[i] return s[1:]
(gdb) p table->alias $1 = _binary "t3" (gdb) p &table->alias $2 = (String *) 0x7fffd409c250 _binary "t3" (gdb) p table->read_set[0] $3 = b'10011' (gdb) p thd->variables.sql_mode $4 = STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION (gdb) p ha_alter_info.handler_flags $5 = ADD_INDEX,DROP_INDEX,ADD_PK_INDEX,ALTER_STORED_COLUMN_ORDER
Source: https://habr.com/ru/post/325472/
All Articles