summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2023-03-31 02:54:24 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2023-03-31 02:54:56 -0700
commit98347c251a9c73eba51ffe50519e18334320ac91 (patch)
treebb0ec5de58dbb1c28d0cfa836457822691723431 /misc
parentf803bcfc872b31faeb1b894e315175e410024cd5 (diff)
downloadruby-98347c251a9c73eba51ffe50519e18334320ac91.tar.gz
gdb: Dump env data in cfp command
Diffstat (limited to 'misc')
-rw-r--r--misc/gdb.py75
1 files 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})'))