From 98347c251a9c73eba51ffe50519e18334320ac91 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 31 Mar 2023 02:54:24 -0700 Subject: gdb: Dump env data in cfp command --- misc/gdb.py | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/misc/gdb.py b/misc/gdb.py index 038ebfc069..6f26fc1111 100644 --- a/misc/gdb.py +++ b/misc/gdb.py @@ -2,6 +2,34 @@ # cfp: Dump the current cfp # cfp + 1: Dump the caller cfp class CFP(gdb.Command): + FRAME_MAGICS = [ + # frame types + 'VM_FRAME_MAGIC_METHOD', + 'VM_FRAME_MAGIC_BLOCK', + 'VM_FRAME_MAGIC_CLASS', + 'VM_FRAME_MAGIC_TOP', + 'VM_FRAME_MAGIC_CFUNC', + 'VM_FRAME_MAGIC_IFUNC', + 'VM_FRAME_MAGIC_EVAL', + 'VM_FRAME_MAGIC_RESCUE', + 'VM_FRAME_MAGIC_DUMMY', + ] + FRAME_FLAGS = [ + # frame flag + 'VM_FRAME_FLAG_FINISH', + 'VM_FRAME_FLAG_BMETHOD', + 'VM_FRAME_FLAG_CFRAME', + 'VM_FRAME_FLAG_LAMBDA', + 'VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM', + 'VM_FRAME_FLAG_CFRAME_KW', + 'VM_FRAME_FLAG_PASSED', + # env flag + 'VM_ENV_FLAG_LOCAL', + 'VM_ENV_FLAG_ESCAPED', + 'VM_ENV_FLAG_WB_REQUIRED', + 'VM_ENV_FLAG_ISOLATED', + ] + def __init__(self): super(CFP, self).__init__('cfp', gdb.COMMAND_USER) @@ -17,12 +45,53 @@ class CFP(gdb.Command): gdb.execute(f'p *({cfp})') print() + print('Env:') + self.print_stack(cfp, -3, self.rp(cfp, -3)) + self.print_stack(cfp, -2, self.specval(cfp, -2)) + self.print_stack(cfp, -1, self.frame_types(cfp, -1)) + print() + stack_size = int((self.get_int(f'{cfp}->sp') - self.get_int(f'{cfp}->__bp__')) / 8) print(f'Stack (size={stack_size}):') for i in range(0, stack_size): - obj = self.get_int(f'{cfp}->__bp__[{i}]') - rp = self.get_string(f'rp {obj}') - print(f'[{i}] {rp}', end='') + self.print_stack(cfp, i, self.rp(cfp, i)) + + def print_stack(self, cfp, bp_index, content): + address = self.get_int(f'{cfp}->__bp__ + {bp_index}') + print('0x{:x} [{}] {}'.format(address, bp_index, content)) + + def rp(self, cfp, bp_index): + value = self.get_value(cfp, bp_index) + return self.get_string(f'rp {value}').rstrip() + + # specval: block_handler or previous EP + def specval(self, cfp, bp_index): + value = self.get_value(cfp, bp_index) + specval = '0x{:x}'.format(value) + for block_handler in ['VM_BLOCK_HANDLER_NONE', 'rb_block_param_proxy']: + if value == self.get_int(block_handler): + return f'{specval} ({block_handler})' + return specval + + def frame_types(self, cfp, bp_index): + types = [] + value = self.get_value(cfp, bp_index) + + magic_mask = self.get_int('VM_FRAME_MAGIC_MASK') + for magic in self.FRAME_MAGICS: + magic_value = self.get_int(magic) + if value & magic_mask == magic_value: + types.append(magic) + + for flag in self.FRAME_FLAGS: + flag_value = self.get_int(flag) + if value & flag_value: + types.append(flag) + + return '0x{:x} ({})'.format(self.get_value(cfp, bp_index), ' | '.join(types)) + + def get_value(self, cfp, bp_index): + return self.get_int(f'{cfp}->__bp__[{bp_index}]') def get_int(self, expr): return int(self.get_string(f'printf "%ld", ({expr})')) -- cgit v1.2.3