Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDB script improvements #17227

Open
wants to merge 21 commits into
base: master
Choose a base branch
from

Conversation

arnaud-lb
Copy link
Member

@arnaud-lb arnaud-lb commented Dec 20, 2024

Improve the Python GDB script in the following ways:

  • Support IS_INDIRECT, IS_PTR, IS_ALIAS_PTR when printing zvals:
(gdb) p $z1
$3 = (zval *) 0x7ffff7a5f040
(gdb) p *$z1
$4 = ((zval *) 0x7ffff7a5f040) indirect: ((zval*) 0x7ffff7a58628) "foo" = {
  ... (zval fields)
}

(gdb) p $z2
$6 = (zval *) 0x1356580
(gdb) p *$z2
$7 = ((zval *) 0x1356580) ptr: ((void*) 0x7ffff7a02018) = {
  ... (zval fields)
}
  • Pretty print the ce_flags field when pretty printing a zend_class_entry
(gdb) p Z_CE_P($z2)
$9 = ((zend_class_entry *) 0x7ffff7a02220) "C" = {
  type = 2 '\002',
  name = "C",
  <anonymous> = {
    parent = 0x0,
    parent_name = 0x0
  },
  refcount = 1,
  ce_flags = 4872 (ZEND_ACC_LINKED | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_TOP_LEVEL | ZEND_ACC_CONSTANTS_UPDATED),
  ... (other zend_class_entry fields)
  • Pretty print the const flags when pretty printing a zend_class_constant
(gdb) p $c
$4 = (zend_class_constant *) 0x7ffff7a02220
(gdb) p *$c
$5 = ((zend_class_constant *) 0x7ffff7a02220) {
  value.u2.constant_flags = 1 (ZEND_ACC_PUBLIC),
  ... (other zend_class_constant fields)
}
  • Added a minimal zend_property_info pretty printer to pretty print the flags field
(gdb) p $p
$10 = (struct _zend_property_info *) 0x7ffff7a02258
(gdb) p *$p
$11 = {
  offset = 40,
  flags = 1 (ZEND_ACC_PUBLIC),
  name = "foo",
  ... (other zend_property_info fields)
}
  • Added minimal zend_function, zend_op_array, and zend_internal_function pretty printers:
    • The the string value is the function/method name, function type (user/internal), and location (when application)
    • Pretty print fn_flags field
(gdb) p $f
$13 = (zend_function *) 0x7ffff7a022a0
(gdb) p *$f
$14 = ((zend_function *) 0x7ffff7a022a0) user method "C"::"foo" "Command line code":1 = {
  type = 2 '\002',
  quick_arg_flags = 2,
  op_array = ((zend_op_array *) 0x7ffff7a022a0) method "C"::"foo" "Command line code":1 = {
    type = 2 '\002',
    arg_flags = "\000\000",
    fn_flags = 33554466 (ZEND_ACC_PROTECTED | ZEND_ACC_FINAL | ZEND_ACC_DONE_PASS_TWO),
  ... (other fields)
}
  • Added a minimal zend_op pretty printer to pretty print the opcode
(gdb) p $f.op_array.opcodes[0]
$15 = {
  opcode = 62 (ZEND_RETURN),
  ... (other zend_op fields)
}
  • Added a zend_refcounted_h pretty printer to pretty print the type_info
(gdb) p struc.value.obj.gc
$76 = {
  refcount = 3,
  u.type_info = 3221226632 (IS_OBJECT | IS_OBJ_WEAKLY_REFERENCED(GC_PERSISTENT) | GC_PURPLE | GC_ADDRESS(1))
}
  • Added minimal pretty printers for zend_object and zend_array:
(gdb) p *$obj
$77 = object("stdClass") = {
  ...
}

(gdb) p *$arr
$79 = array(2) = {
  ...
}

(This doesn't print members yet, but the print_ht commands from .gdbinit can be used for that)

  • Print the type and address of pretty-printed structs:

Before:

(gdb) p *zv
$15 = "foo" = {
  value = "foo" = {

After:

(gdb) p *zv
$15 = ((zval*) 0x7ffff7a130d0) "foo" = {
  value = ((zend_string*) 0x7ffff7a01cc0) "foo" = {
  • Added a few gdb commands:
    • print_fn_flags, print_ce_flags, print_prop_flags, print_const_flags
    • print_opcode
    • print_ref_type_info
(gdb) print_fn_flags 33554466
ZEND_ACC_PROTECTED | ZEND_ACC_FINAL | ZEND_ACC_DONE_PASS_TWO
(gdb) print_ce_flags 4872
ZEND_ACC_LINKED | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_TOP_LEVEL | ZEND_ACC_CONSTANTS_UPDATED
(gdb) print_prop_flags 1
ZEND_ACC_PUBLIC
(gdb) print_const_flags 1
ZEND_ACC_PUBLIC

(gdb) print_opcode 1
ZEND_ADD

(gdb) print_ref_type_info 71
IS_ARRAY | IS_ARRAY_IMMUTABLE(GC_IMMUTABLE) | GC_BLACK
  • Fields of type zend_string, zend_class_entry, zend_array are printed by default in all our pretty printers, using short representation
  • Increased the maximum length of printed strings (before truncation) to 200 chars (from 50)
  • Small refactors

@iluuu1994
Copy link
Member

Very nice improvements! It would also be nice to have direct pretty printing support of zend_object, HashTable, and zend_refcounted, when not working with zval directly.

@arnaud-lb
Copy link
Member Author

@iluuu1994 I've added a pretty printer for zend_refcounted_h and a command to pretty print a zend_refcounted_h.u.type_info value. Also, minimal printers for objects and arrays. I plan to add support for printing array elements at some point, but the print_ht command from .gdbinit works well already.

@arnaud-lb arnaud-lb marked this pull request as ready for review January 9, 2025 16:46
@arnaud-lb arnaud-lb requested a review from bukka as a code owner January 9, 2025 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants