1 /* 2 +----------------------------------------------------------------------+ 3 | Copyright (c) The PHP Group | 4 +----------------------------------------------------------------------+ 5 | This source file is subject to version 3.01 of the PHP license, | 6 | that is bundled with this package in the file LICENSE, and is | 7 | available through the world-wide-web at the following url: | 8 | https://www.php.net/license/3_01.txt | 9 | If you did not receive a copy of the PHP license and are unable to | 10 | obtain it through the world-wide-web, please send a note to | 11 | license@php.net so we can mail you a copy immediately. | 12 +----------------------------------------------------------------------+ 13 | Authors: Felipe Pena <felipe@php.net> | 14 | Authors: Joe Watkins <joe.watkins@live.co.uk> | 15 | Authors: Bob Weinand <bwoebi@php.net> | 16 +----------------------------------------------------------------------+ 17 */ 18 19 #ifndef PHPDBG_H 20 #define PHPDBG_H 21 22 #ifdef PHP_WIN32 23 # define PHPDBG_API __declspec(dllexport) 24 #elif defined(__GNUC__) && __GNUC__ >= 4 25 # define PHPDBG_API __attribute__ ((visibility("default"))) 26 #else 27 # define PHPDBG_API 28 #endif 29 30 #include <stdint.h> 31 #include <stddef.h> 32 #include "php.h" 33 #include "php_globals.h" 34 #include "php_variables.h" 35 #include "php_getopt.h" 36 #include "zend_builtin_functions.h" 37 #include "zend_extensions.h" 38 #include "zend_modules.h" 39 #include "zend_globals.h" 40 #include "zend_ini_scanner.h" 41 #include "zend_stream.h" 42 #include "zend_signal.h" 43 #if !defined(_WIN32) && !defined(ZEND_SIGNALS) 44 # include <signal.h> 45 #elif defined(PHP_WIN32) 46 # include "win32/signal.h" 47 #endif 48 #include "SAPI.h" 49 #include <fcntl.h> 50 #include <sys/types.h> 51 #if defined(_WIN32) && !defined(__MINGW32__) 52 # include <windows.h> 53 # include "config.w32.h" 54 # undef strcasecmp 55 # undef strncasecmp 56 # define strcasecmp _stricmp 57 # define strncasecmp _strnicmp 58 #else 59 # include <php_config.h> 60 #endif 61 #ifndef O_BINARY 62 # define O_BINARY 0 63 #endif 64 #include "php_main.h" 65 66 #ifdef ZTS 67 # include "TSRM.h" 68 #endif 69 70 #undef zend_hash_str_add 71 #ifdef PHP_WIN32 72 #define zend_hash_str_add(...) \ 73 zend_hash_str_add(__VA_ARGS__) 74 #else 75 #define zend_hash_str_add_tmp(ht, key, len, pData) \ 76 zend_hash_str_add(ht, key, len, pData) 77 #define zend_hash_str_add(...) zend_hash_str_add_tmp(__VA_ARGS__) 78 #endif 79 80 #ifdef HAVE_PHPDBG_READLINE 81 # ifdef HAVE_LIBREADLINE 82 # include <readline/readline.h> 83 # include <readline/history.h> 84 # endif 85 # ifdef HAVE_LIBEDIT 86 # include <editline/readline.h> 87 # endif 88 #endif 89 90 /* {{{ strings */ 91 #define PHPDBG_NAME "phpdbg" 92 #define PHPDBG_AUTHORS "Felipe Pena, Joe Watkins and Bob Weinand" /* Ordered by last name */ 93 #define PHPDBG_ISSUES "https://github.com/php/php-src/issues" 94 #define PHPDBG_VERSION PHP_VERSION 95 #define PHPDBG_INIT_FILENAME ".phpdbginit" 96 #define PHPDBG_DEFAULT_PROMPT "prompt>" 97 /* }}} */ 98 99 #ifdef ZTS 100 # define PHPDBG_G(v) ZEND_TSRMG(phpdbg_globals_id, zend_phpdbg_globals *, v) 101 #else 102 # define PHPDBG_G(v) (phpdbg_globals.v) 103 #endif 104 105 #include "phpdbg_sigsafe.h" 106 #include "phpdbg_out.h" 107 #include "phpdbg_lexer.h" 108 #include "phpdbg_cmd.h" 109 #include "phpdbg_utils.h" 110 #include "phpdbg_btree.h" 111 #include "phpdbg_watch.h" 112 #include "phpdbg_bp.h" 113 114 int phpdbg_do_parse(phpdbg_param_t *stack, char *input); 115 116 #define PHPDBG_NEXT 2 117 #define PHPDBG_UNTIL 3 118 #define PHPDBG_FINISH 4 119 #define PHPDBG_LEAVE 5 120 121 /* 122 BEGIN: DO NOT CHANGE DO NOT CHANGE DO NOT CHANGE 123 */ 124 125 /* {{{ flags */ 126 #define PHPDBG_HAS_FILE_BP (1ULL<<1) 127 #define PHPDBG_HAS_PENDING_FILE_BP (1ULL<<2) 128 #define PHPDBG_HAS_SYM_BP (1ULL<<3) 129 #define PHPDBG_HAS_OPLINE_BP (1ULL<<4) 130 #define PHPDBG_HAS_METHOD_BP (1ULL<<5) 131 #define PHPDBG_HAS_COND_BP (1ULL<<6) 132 #define PHPDBG_HAS_OPCODE_BP (1ULL<<7) 133 #define PHPDBG_HAS_FUNCTION_OPLINE_BP (1ULL<<8) 134 #define PHPDBG_HAS_METHOD_OPLINE_BP (1ULL<<9) 135 #define PHPDBG_HAS_FILE_OPLINE_BP (1ULL<<10) /* }}} */ 136 137 /* 138 END: DO NOT CHANGE DO NOT CHANGE DO NOT CHANGE 139 */ 140 141 #define PHPDBG_IN_COND_BP (1ULL<<11) 142 #define PHPDBG_IN_EVAL (1ULL<<12) 143 144 #define PHPDBG_IS_STEPPING (1ULL<<13) 145 #define PHPDBG_STEP_OPCODE (1ULL<<14) 146 #define PHPDBG_IS_QUIET (1ULL<<15) 147 #define PHPDBG_IS_QUITTING (1ULL<<16) 148 #define PHPDBG_IS_COLOURED (1ULL<<17) 149 #define PHPDBG_IS_CLEANING (1ULL<<18) 150 #define PHPDBG_IS_RUNNING (1ULL<<19) 151 152 #define PHPDBG_IN_UNTIL (1ULL<<20) 153 #define PHPDBG_IN_FINISH (1ULL<<21) 154 #define PHPDBG_IN_LEAVE (1ULL<<22) 155 156 #define PHPDBG_IS_REGISTERED (1ULL<<23) 157 #define PHPDBG_IS_STEPONEVAL (1ULL<<24) 158 #define PHPDBG_IS_INITIALIZING (1ULL<<25) 159 #define PHPDBG_IS_SIGNALED (1ULL<<26) 160 #define PHPDBG_IS_INTERACTIVE (1ULL<<27) 161 #define PHPDBG_PREVENT_INTERACTIVE (1ULL<<28) 162 #define PHPDBG_IS_BP_ENABLED (1ULL<<29) 163 #define PHPDBG_SHOW_REFCOUNTS (1ULL<<30) 164 #define PHPDBG_IN_SIGNAL_HANDLER (1ULL<<31) 165 #define PHPDBG_DISCARD_OUTPUT (1ULL<<32) 166 #define PHPDBG_HAS_PAGINATION (1ULL<<33) 167 168 #define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL | PHPDBG_IN_FINISH | PHPDBG_IN_LEAVE) 169 #define PHPDBG_BP_RESOLVE_MASK (PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP) 170 #define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP | PHPDBG_HAS_SYM_BP | PHPDBG_HAS_METHOD_BP | PHPDBG_HAS_OPLINE_BP | PHPDBG_HAS_COND_BP | PHPDBG_HAS_OPCODE_BP | PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP) 171 #define PHPDBG_IS_STOPPING (PHPDBG_IS_QUITTING | PHPDBG_IS_CLEANING) 172 173 #define PHPDBG_PRESERVE_FLAGS_MASK \ 174 (PHPDBG_SHOW_REFCOUNTS | \ 175 PHPDBG_IS_STEPONEVAL | \ 176 PHPDBG_IS_BP_ENABLED | \ 177 PHPDBG_STEP_OPCODE | \ 178 PHPDBG_IS_QUIET | \ 179 PHPDBG_IS_COLOURED | \ 180 PHPDBG_HAS_PAGINATION) 181 182 #ifndef _WIN32 183 # define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET | PHPDBG_IS_COLOURED | PHPDBG_IS_BP_ENABLED | PHPDBG_HAS_PAGINATION) 184 #else 185 # define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET | PHPDBG_IS_BP_ENABLED | PHPDBG_HAS_PAGINATION) 186 #endif /* }}} */ 187 188 /* {{{ output descriptors */ 189 #define PHPDBG_STDIN 0 190 #define PHPDBG_STDOUT 1 191 #define PHPDBG_STDERR 2 192 #define PHPDBG_IO_FDS 3 /* }}} */ 193 194 #define phpdbg_try_access \ 195 { \ 196 ZEND_DIAGNOSTIC_IGNORED_START("-Wshadow") \ 197 JMP_BUF *__orig_bailout = PHPDBG_G(sigsegv_bailout); \ 198 JMP_BUF __bailout; \ 199 ZEND_DIAGNOSTIC_IGNORED_END \ 200 \ 201 PHPDBG_G(sigsegv_bailout) = &__bailout; \ 202 if (SETJMP(__bailout) == 0) { 203 #define phpdbg_catch_access \ 204 } else { \ 205 PHPDBG_G(sigsegv_bailout) = __orig_bailout; 206 #define phpdbg_end_try_access() \ 207 } \ 208 PHPDBG_G(sigsegv_bailout) = __orig_bailout; \ 209 } 210 211 212 void phpdbg_register_file_handles(void); 213 214 typedef struct _phpdbg_oplog_entry phpdbg_oplog_entry; 215 struct _phpdbg_oplog_entry { 216 phpdbg_oplog_entry *next; 217 zend_string *function_name; 218 zend_class_entry *scope; 219 zend_string *filename; 220 zend_op *opcodes; 221 zend_op *op; 222 }; 223 224 typedef struct _phpdbg_oplog_list phpdbg_oplog_list; 225 struct _phpdbg_oplog_list { 226 phpdbg_oplog_list *prev; 227 phpdbg_oplog_entry start; /* Only "next" member used. */ 228 }; 229 230 231 /* {{{ structs */ 232 ZEND_BEGIN_MODULE_GLOBALS(phpdbg) 233 HashTable bp[PHPDBG_BREAK_TABLES]; /* break points */ 234 HashTable registered; /* registered */ 235 HashTable seek; /* seek oplines */ 236 zend_execute_data *seek_ex; /* call frame of oplines to seek to */ 237 zend_object *handled_exception; /* last handled exception (prevent multiple handling of same exception) */ 238 phpdbg_frame_t frame; /* frame */ 239 uint32_t last_line; /* last executed line */ 240 241 char *cur_command; /* current command */ 242 phpdbg_lexer_data lexer; /* lexer data */ 243 phpdbg_param_t *parser_stack; /* param stack during lexer / parser phase */ 244 245 #ifndef _WIN32 246 struct sigaction old_sigsegv_signal; /* segv signal handler */ 247 #endif 248 #ifdef HAVE_USERFAULTFD_WRITEFAULT 249 int watch_userfaultfd; /* userfaultfd(2) handler, 0 if unused */ 250 pthread_t watch_userfault_thread; /* thread for watch fault handling */ 251 #endif 252 phpdbg_btree watchpoint_tree; /* tree with watchpoints */ 253 phpdbg_btree watch_HashTables; /* tree with original dtors of watchpoints */ 254 HashTable watch_elements; /* user defined watch elements */ 255 HashTable watch_collisions; /* collision table to check if multiple watches share the same recursive watchpoint */ 256 HashTable watch_recreation; /* watch elements pending recreation of their respective watchpoints */ 257 HashTable watch_free; /* pointers to watch for being freed */ 258 HashTable *watchlist_mem; /* triggered watchpoints */ 259 HashTable *original_watchlist_mem; /* the original allocation for watchlist_mem, used when watchlist_mem has changed temporarily */ 260 HashTable *watchlist_mem_backup; /* triggered watchpoints backup table while iterating over it */ 261 bool watchpoint_hit; /* a watchpoint was hit */ 262 void (*original_free_function)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); /* the original AG(mm_heap)->_free function */ 263 phpdbg_watch_element *watch_tmp; /* temporary pointer for a watch element */ 264 265 char *exec; /* file to execute */ 266 size_t exec_len; /* size of exec */ 267 zend_op_array *ops; /* op_array */ 268 zval retval; /* return value */ 269 int bp_count; /* breakpoint count */ 270 int vmret; /* return from last opcode handler execution */ 271 bool in_execution; /* in execution? */ 272 bool unclean_eval; /* do not check for memory leaks when we needed to bail out during eval */ 273 274 zend_op_array *(*compile_file)(zend_file_handle *file_handle, int type); 275 zend_op_array *(*init_compile_file)(zend_file_handle *file_handle, int type); 276 zend_op_array *(*compile_string)(zend_string *source_string, const char *filename, zend_compile_position position); 277 HashTable file_sources; 278 279 zend_arena *oplog_arena; /* arena for storing oplog */ 280 phpdbg_oplog_list *oplog_list; /* list of oplog starts */ 281 phpdbg_oplog_entry *oplog_cur; /* current oplog entry */ 282 283 struct { 284 int fd; 285 } io[PHPDBG_IO_FDS]; /* io */ 286 ssize_t (*php_stdiop_write)(php_stream *, const char *, size_t); 287 struct { 288 bool active; 289 int type; 290 int fd; 291 char *msg; 292 int msglen; 293 } err_buf; /* error buffer */ 294 zend_ulong req_id; /* "request id" to keep track of commands */ 295 296 char *prompt[2]; /* prompt */ 297 const phpdbg_color_t *colors[PHPDBG_COLORS]; /* colors */ 298 char *buffer; /* buffer */ 299 bool last_was_newline; /* check if we don't need to output a newline upon next phpdbg_error or phpdbg_notice */ 300 301 FILE *stdin_file; /* FILE pointer to stdin source file */ 302 const php_stream_wrapper *orig_url_wrap_php; 303 304 char input_buffer[PHPDBG_MAX_CMD]; /* stdin input buffer */ 305 int input_buflen; /* length of stdin input buffer */ 306 phpdbg_signal_safe_mem sigsafe_mem; /* memory to use in async safe environment (only once!) */ 307 308 JMP_BUF *sigsegv_bailout; /* bailout address for accessibility probing */ 309 310 uint64_t flags; /* phpdbg flags */ 311 312 char *sapi_name_ptr; /* store sapi name to free it if necessary to not leak memory */ 313 zend_ulong lines; /* max number of lines to display */ 314 ZEND_END_MODULE_GLOBALS(phpdbg) /* }}} */ 315 316 #endif /* PHPDBG_H */ 317