42#include "phpdbg_parser.h"
44#if ZEND_VM_KIND != ZEND_VM_KIND_CALL && ZEND_VM_KIND != ZEND_VM_KIND_HYBRID
45#error "phpdbg can only be built with CALL zend vm kind"
55#define GET_DL_ERROR() php_win_err()
58#define GET_DL_ERROR() DL_ERROR()
130 char *buffered =
NULL;
132 switch (
next->type) {
214 size_t cmd_len =
strlen(cmd);
218 while (cmd_len > 0L && isspace(cmd[cmd_len-1])) {
224 if (*cmd && cmd_len > 0L && cmd[0] !=
'#') {
226 if (memcmp(cmd,
"<:",
sizeof(
"<:")-1) ==
SUCCESS) {
230 if (memcmp(cmd,
":>",
sizeof(
":>")-1) ==
SUCCESS) {
241 if (
state->in_code) {
243 state->code = malloc(cmd_len + 1);
250 state->code_len += cmd_len;
268 if (phpdbg_call_register(&stack) ==
FAILURE) {
269 if (
state->init_file) {
299 phpdbg_line_init(str, &
state);
322 phpdbg_line_init(cmd, &
state);
344 }
else if (use_default) {
345 char *scan_dir =
getenv(
"PHP_INI_SCAN_DIR");
356 while (*scan_dir != 0) {
358 while (scan_dir[i] !=
':') {
359 if (scan_dir[i++] == 0) {
406 if (sb.st_mode & (S_IFREG|
S_IFLNK)) {
451 phpdbg_error(
"Cannot use %s as execution context, not a valid file or symlink", param->str);
454 phpdbg_error(
"Cannot stat %s, ensure the file exists", param->str);
463 char *sep = param->str;
464 int seplen = param->len;
467 smart_str_appends(&
code,
"?>");
478 if (
buf == nl + seplen) {
479 if (!memcmp(sep, nl, seplen) && (*
buf ==
'\n' || (*
buf ==
'\r' &&
buf[1] ==
'\n'))) {
490 if (
buf != nl &&
buf <= nl + seplen) {
522 zend_string_release(
code);
543 zend_string_release(source_path);
545 for (i = 1; i <=
data->lines; i++) {
570 CG(skip_shebang) = 1;
610 if (opline->
lineno !=
ex->opline->lineno
619 }
while (++opline < op_array->opcodes + op_array->
last);
646static void phpdbg_seek_to_end(
void) {
661 }
while (++opline < op_array->opcodes + op_array->
last);
672 phpdbg_seek_to_end();
689 phpdbg_seek_to_end();
690 if (zend_hash_index_exists(&
PHPDBG_G(
seek), (
zend_ulong) phpdbg_user_execute_data(
EG(current_execute_data))->opline)) {
711static inline void phpdbg_handle_exception(
void)
720 zend_call_known_instance_method_with_0_params(
ex->ce->__tostring,
ex, &tmp);
734 zend_string_release(
file);
736 zend_string_release(
msg);
738 if (
EG(prev_exception)) {
740 EG(prev_exception) = 0;
743 EG(opline_before_exception) =
NULL;
745 EG(exit_status) = 255;
770 if (param && param->type !=
EMPTY_PARAM && param->len != 0) {
771 char **argv =
emalloc(5 *
sizeof(
char *));
772 char *
end = param->str + param->len, *
p = param->str;
777 while (*
end ==
'\r' || *
end ==
'\n') *(
end--) = 0;
781 while (*
p ==
' ')
p++;
788 do p++;
while (*
p ==
' ');
790 if (*
p ==
'\'' || *
p ==
'"') {
793 while (*
p && *
p != sep) {
794 if (*
p ==
'\\' && (
p[1] == sep ||
p[1] ==
'\\')) {
801 do p++;
while (*
p ==
' ');
805 phpdbg_error(
"Invalid run command, cannot put further arguments after stdin");
819 if (argc >= 4 && argc == (argc & -argc)) {
820 argv =
erealloc(argv, (argc * 2 + 1) *
sizeof(
char *));
823 if (*
p ==
'\'' || *
p ==
'"') {
826 if (*
p ==
'\\' && (
p[1] ==
'<' ||
p[1] ==
'\'' ||
p[1] ==
'"')) {
829 while (*
p && *
p != sep) {
830 if (*
p ==
'\\' && (
p[1] == sep ||
p[1] ==
'\\' || (
p[1] ==
'#' && sep ==
' '))) {
835 if (!*
p && sep !=
' ') {
836 phpdbg_error(
"Invalid run command, unterminated escape sequence");
839 for (i = 0; i < argc; i++) {
851 do p++;
while (*
p ==
' ');
856 argv[0] =
SG(request_info).argv[0];
857 for (i =
SG(request_info).argc; --i;) {
858 efree(
SG(request_info).argv[i]);
861 SG(request_info).argv =
erealloc(argv, ++argc *
sizeof(
char *));
862 SG(request_info).argc = argc;
911 phpdbg_handle_exception();
958 phpdbg_error(
"Could not fetch data, invalid data source");
1001 CG(unclean_shutdown) = 0;
1039 if (zend_generator_get_current(gen)->
flags & ZEND_GENERATOR_CURRENTLY_RUNNING) {
1051 for (i = 0; i <
EG(objects_store).top; i++) {
1058 zend_string_release(
s);
1077 return phpdbg_do_print_stack(param);
1078 }
else switch (param->type) {
1080 return phpdbg_do_print_func(param);
1082 return phpdbg_do_print_method(param);
1084 phpdbg_error(
"Invalid arguments to print, expected nothing, function name or method name");
1091 phpdbg_out(
"Execution Context Information\n\n");
1092#ifdef HAVE_PHPDBG_READLINE
1093# ifdef HAVE_LIBREADLINE
1123 phpdbg_writeln(
"Functions %d", zend_hash_num_elements(
EG(function_table)));
1124 phpdbg_writeln(
"Constants %d", zend_hash_num_elements(
EG(zend_constants)));
1125 phpdbg_writeln(
"Included %d", zend_hash_num_elements(&
EG(included_files)));
1148 }
else switch (param->type) {
1215PHPDBG_API const char *phpdbg_load_module_or_extension(
char **path,
const char **
name) {
1234 phpdbg_error(
"Not a full path given or extension_dir ini setting is not set");
1243 char *
err = GET_DL_ERROR();
1256#if ZEND_EXTENSIONS_SUPPORT
1261 if (!extension_version_info) {
1265 if (!new_extension) {
1268 if (!extension_version_info || !new_extension) {
1294 return "Zend extension";
1311 module_entry = get_module();
1345 phpdbg_error(
"This shared object is nor a Zend extension nor a module");
1365 }
else switch (param->type) {
1368 path =
estrndup(param->str, param->len);
1371 if ((
type = phpdbg_load_module_or_extension(&path, &
name)) ==
NULL) {
1380 phpdbg_error(
"Cannot dynamically load %.*s - dynamic modules are not supported", (
int) param->len, param->str);
1397 phpdbg_error(
"Failed to stat %s, file does not exist", param->str);
1411 phpdbg_error(
"Failed to open or create %s, check path and permissions", param->str);
1421 size_t lcname_len = param->len;
1424 if ((
function = zend_hash_str_find_ptr(
EG(function_table),
lcname, lcname_len))) {
1429 phpdbg_error(
"The requested function (%s) could not be found", param->str);
1455 phpdbg_out(
"Cleaning Execution Environment\n");
1458 phpdbg_writeln(
"Functions %d", zend_hash_num_elements(
EG(function_table)));
1459 phpdbg_writeln(
"Constants %d", zend_hash_num_elements(
EG(zend_constants)));
1460 phpdbg_writeln(
"Includes %d", zend_hash_num_elements(&
EG(included_files)));
1489 }
else switch (param->type) {
1513 }
else switch (param->type) {
1558 if (!allow_async_unsafe || phpdbg_call_register(&stack) ==
FAILURE) {
1606static inline void list_code(
void) {
1616#define DO_INTERACTIVE(allow_async_unsafe) do { \
1618 const zend_op *before_ex = EG(opline_before_exception); \
1619 const zend_op *backup_opline = NULL; \
1620 if (EG(current_execute_data) && EG(current_execute_data)->func && ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) { \
1621 backup_opline = EG(current_execute_data)->opline; \
1623 GC_ADDREF(exception); \
1624 zend_clear_exception(); \
1626 switch (phpdbg_interactive(allow_async_unsafe, NULL)) { \
1627 case PHPDBG_LEAVE: \
1628 case PHPDBG_FINISH: \
1629 case PHPDBG_UNTIL: \
1632 && (backup_opline->opcode == ZEND_HANDLE_EXCEPTION || backup_opline->opcode == ZEND_CATCH)) { \
1633 EG(current_execute_data)->opline = backup_opline; \
1634 EG(exception) = exception; \
1636 zend_throw_exception_internal(exception); \
1638 EG(opline_before_exception) = before_ex; \
1642 phpdbg_interactive(allow_async_unsafe, NULL); \
1657#ifdef ZEND_CHECK_STACK_LIMIT
1658 if (
UNEXPECTED(zend_call_stack_overflowed(
EG(stack_limit)))) {
1661 EG(opline_before_exception) =
NULL;
1675 if (zend_atomic_bool_load_ex(&
EG(timed_out))) {
1716 zend_string_release(
msg);
1717 zend_string_release(
file);
1744#define INDEX_EXISTS_CHECK (zend_hash_index_exists(&PHPDBG_G(seek), address) || (exception && phpdbg_check_caught_ex(execute_data, exception) == 0))
1855 (uint32_t) (
data->opline -
data->func->op_array.opcodes),
1856 data->func->op_array.filename->val,
1857 data->opline->lineno);
1858 }
else if (
data->func->internal_function.function_name) {
1860 data->func->internal_function.function_name->val);
1865 phpdbg_notice(
"Current opline: %p (op_array information unavailable)",
1869 phpdbg_notice(
"No information available about executing context");
file_private const char ext[]
getenv(?string $name=null, bool $local_only=false)
file(string $filename, int $flags=0, $context=null)
strtok(string $string, ?string $token=null)
fopen(string $filename, string $mode, bool $use_include_path=false, $context=null)
fgets($stream, ?int $length=null)
strchr(string $haystack, string $needle, bool $before_needle=false)
dl(string $extension_filename)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
const php_stream_filter_ops * ops
PHPAPI zend_result php_stream_open_for_zend_ex(zend_file_handle *handle, int mode)
const PHP_CONFIG_FILE_SCAN_DIR
const PHP_CONFIG_FILE_PATH
unsigned const char * end
#define TRACK_VARS_SERVER
php_output_handler * active
#define STREAM_OPEN_FOR_INCLUDE
PHPAPI void php_build_argv(const char *s, zval *track_vars_array)
void phpdbg_register_file_handles(void)
HashTable bp[PHPDBG_BREAK_TABLES]
struct @010122165316201240231237266310115370127155020222 err_buf
struct @234323133100145062121301312242002332057146367313 io[PHPDBG_IO_FDS]
int phpdbg_do_parse(phpdbg_param_t *stack, char *input)
#define PHPDBG_IS_STEPONEVAL
#define PHPDBG_IS_INTERACTIVE
#define PHPDBG_IS_INITIALIZING
#define phpdbg_try_access
zend_object * handled_exception
#define phpdbg_catch_access
#define PHPDBG_STEP_OPCODE
char input_buffer[PHPDBG_MAX_CMD]
#define PHPDBG_IS_STEPPING
zend_execute_data * seek_ex
#define PHPDBG_BP_RESOLVE_MASK
#define PHPDBG_INIT_FILENAME
#define phpdbg_end_try_access()
#define PHPDBG_IN_SIGNAL_HANDLER
#define PHPDBG_IN_COND_BP
#define PHPDBG_IS_SIGNALED
#define PHPDBG_PREVENT_INTERACTIVE
#define PHPDBG_IS_RUNNING
#define PHPDBG_IS_QUITTING
#define PHPDBG_IS_STOPPING
#define PHPDBG_IS_CLEANING
PHPDBG_API phpdbg_breakbase_t * phpdbg_find_breakpoint(zend_execute_data *execute_data)
PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend_ulong opline)
PHPDBG_API void phpdbg_resolve_op_array_breaks(zend_op_array *op_array)
PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline)
PHPDBG_API void phpdbg_clear_breakpoints(void)
PHPDBG_API void phpdbg_hit_breakpoint(phpdbg_breakbase_t *brake, bool output)
PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len)
PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, size_t path_len, zend_ulong line_num)
PHPDBG_API void phpdbg_export_breakpoints(FILE *handle)
PHPDBG_API void phpdbg_reset_breakpoints(void)
PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const char *method, zend_ulong opline)
PHPDBG_API void phpdbg_set_breakpoint_expression(const char *expr, size_t expr_len)
PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len)
PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong opline)
PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char *func_name)
#define PHPDBG_BREAK_FUNCTION_OPLINE
#define PHPDBG_BREAK_COND
#define PHPDBG_BREAK_FILE_OPLINE
#define PHPDBG_BREAK_OPLINE
#define PHPDBG_BREAK_METHOD
#define PHPDBG_BREAK_METHOD_OPLINE
#define PHPDBG_BREAK_FILE
struct _phpdbg_breakbase_t phpdbg_breakbase_t
const phpdbg_command_t phpdbg_break_commands[]
PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, bool allow_async_unsafe)
PHPDBG_API char * phpdbg_read_input(const char *buffered)
PHPDBG_API void phpdbg_destroy_input(char **input)
PHPDBG_API int phpdbg_ask_user_permission(const char *question)
PHPDBG_API void phpdbg_stack_free(phpdbg_param_t *stack)
struct _phpdbg_param phpdbg_param_t
#define PHPDBG_COMMAND(name)
#define PHPDBG_END_COMMAND
#define phpdbg_init_param(v, t)
#define phpdbg_default_switch_case()
#define PHPDBG_COMMAND_ARGS
struct _phpdbg_command_t phpdbg_command_t
#define PHPDBG_COMMAND_D(name, tip, alias, children, args, flags)
#define PHPDBG_ASYNC_SAFE
void phpdbg_open_generator_frame(zend_generator *gen)
zend_string * phpdbg_compile_stackframe(zend_execute_data *ex)
void phpdbg_dump_backtrace(size_t num)
void phpdbg_switch_frame(int frame)
void phpdbg_restore_frame(void)
const phpdbg_command_t phpdbg_help_commands[]
const phpdbg_command_t phpdbg_info_commands[]
PHPDBG_API int phpdbg_mixed_read(int fd, char *ptr, int len, int tmo)
void phpdbg_list_function_byname(const char *str, size_t len)
const phpdbg_command_t phpdbg_list_commands[]
void phpdbg_list_file(zend_string *filename, uint32_t count, int offset, uint32_t highlight)
#define PHPDBG_LIST_HANDLER(name)
PHPDBG_API void phpdbg_free_err_buf(void)
PHPDBG_API void phpdbg_activate_err_buf(bool active)
PHPDBG_API int phpdbg_output_err_buf(const char *strfmt,...)
#define phpdbg_error(strfmt,...)
#define phpdbg_out(fmt,...)
#define phpdbg_write(strfmt,...)
#define phpdbg_notice(strfmt,...)
#define phpdbg_debug(strfmt,...)
#define phpdbg_writeln(strfmt,...)
const phpdbg_command_t phpdbg_print_commands[]
void phpdbg_print_opline(zend_execute_data *execute_data, bool ignore_flags)
void phpdbg_init(char *init_file, size_t init_file_len, bool use_default)
#define INDEX_EXISTS_CHECK
void phpdbg_string_init(char *buffer)
const phpdbg_command_t phpdbg_prompt_commands[]
int phpdbg_skip_line_helper(void)
void phpdbg_try_file_init(char *init_file, size_t init_file_len, bool free_init)
int phpdbg_output_ev_variable(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv)
PHPDBG_OUTPUT_BACKUP_RESTORE()
int phpdbg_compile_stdin(zend_string *code)
zend_execute_data * original_execute_data
#define DO_INTERACTIVE(allow_async_unsafe)
void phpdbg_clean(bool full, bool resubmit)
zend_vm_stack original_stack
void phpdbg_force_interruption(void)
void phpdbg_execute_ex(zend_execute_data *execute_data)
int phpdbg_interactive(bool allow_async_unsafe, char *input)
const phpdbg_command_t phpdbg_set_commands[]
PHPDBG_API char * phpdbg_resolve_path(const char *path)
PHPDBG_API bool phpdbg_check_caught_ex(zend_execute_data *execute_data, zend_object *exception)
PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_func callback, bool silent)
PHPDBG_API const char * phpdbg_current_file(void)
int phpdbg_print_changed_zvals(void)
int phpdbg_create_var_watchpoint(char *input, size_t len)
void phpdbg_list_watchpoints(void)
const phpdbg_command_t phpdbg_watch_commands[]
zend_execute_data * prev_execute_data
int zend_extension_api_no
int(* build_id_check)(const char *build_id)
int(* api_no_check)(int api_no)
zend_execute_data * execute_data
zend_result(* request_startup_func)(INIT_FUNC_ARGS)
struct _zend_function::@236135173067030250234125302313220025134003177336 common
PHP_WINUTIL_API void php_win32_error_msg_free(char *msg)
ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format,...)
ZEND_API void zend_print_zval_r(zval *expr, int indent)
ZEND_API void zend_append_version_info(const zend_extension *extension)
ZEND_API zval * zend_read_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv)
ZEND_API zend_module_entry * zend_register_module_ex(zend_module_entry *module, int module_type)
ZEND_API zend_result add_next_index_stringl(zval *arg, const char *str, size_t length)
ZEND_API HashTable module_registry
ZEND_API zend_result add_next_index_long(zval *arg, zend_long n)
ZEND_API void zend_update_property_string(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value)
ZEND_API zend_result zend_startup_module_ex(zend_module_entry *module)
ZEND_API zend_result add_next_index_string(zval *arg, const char *str)
struct _zend_fcall_info zend_fcall_info
#define ZEND_EXTERN_MODULE_GLOBALS(module_name)
ZEND_API zend_array * zend_rebuild_symbol_table(void)
#define ZVAL_STRINGL(z, s, l)
ZEND_API zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
#define estrndup(s, length)
#define erealloc(ptr, size)
strcmp(string $string1, string $string2)
ZEND_API zend_op_array *(* zend_compile_file)(zend_file_handle *file_handle, int type)
ZEND_API zend_op_array *(* zend_compile_string)(zend_string *source_string, const char *filename, zend_compile_position position)
#define zend_try_exception_handler()
#define ZEND_USER_CODE(type)
ZEND_API void destroy_op_array(zend_op_array *op_array)
#define ZEND_USER_FUNCTION
#define ZEND_CALL_HAS_SYMBOL_TABLE
struct _zend_op_array zend_op_array
ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle)
#define ZEND_CALL_INFO(call)
@ ZEND_COMPILE_POSITION_AFTER_OPEN_TAG
void zend_exception_restore(void)
ZEND_API bool zend_is_unwind_exit(const zend_object *ex)
ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *ex, int severity)
ZEND_API zend_class_entry * zend_get_exception_base(zend_object *object)
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
ZEND_API uint32_t zend_get_executed_lineno(void)
ZEND_API const char * zend_get_executed_filename(void)
ZEND_API void(* zend_execute_ex)(zend_execute_data *execute_data)
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value)
ZEND_API void execute_ex(zend_execute_data *execute_data)
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_call_stack_size_error(void)
ZEND_API ZEND_NORETURN void ZEND_FASTCALL zend_timeout(void)
ZEND_API zend_result zend_eval_stringl(const char *str, size_t str_len, zval *retval_ptr, const char *string_name)
void zend_register_extension(zend_extension *new_extension, DL_HANDLE handle)
ZEND_API zend_llist zend_extensions
struct _zend_extension_version_info zend_extension_version_info
#define ZEND_EXTENSION_BUILD_ID
struct _zend_extension zend_extension
#define ZEND_EXTENSION_API_NO
union _zend_function zend_function
ZEND_API zend_execute_data * zend_generator_check_placeholder_frame(zend_execute_data *ptr)
ZEND_API zend_class_entry * zend_ce_generator
struct _zend_generator zend_generator
struct _zend_vm_stack * zend_vm_stack
ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_func)
ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
ZEND_API zend_result ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key)
int(* apply_func_t)(zval *pDest)
struct _zend_file_handle zend_file_handle
ZEND_API void zend_llist_apply(zend_llist *l, llist_apply_func_t func)
void(* llist_apply_func_t)(void *)
struct _zend_string zend_string
struct _zend_module_entry zend_module_entry
#define MODULE_PERSISTENT
ZEND_API char *ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length)
#define ZEND_IGNORE_VALUE(x)
#define UNEXPECTED(condition)
struct _zend_object zend_object
ZEND_API zend_result zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t *len)
ZEND_API void zend_stream_init_filename(zend_file_handle *handle, const char *filename)
#define ZSTR_EMPTY_ALLOC()
struct _zend_array HashTable
void(* dtor_func_t)(zval *pDest)
struct _zend_execute_data zend_execute_data
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
#define VCWD_FOPEN(path, mode)
#define VCWD_POPEN(command, type)
#define VCWD_CHDIR_FILE(path)
#define VCWD_STAT(path, buff)
ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data *ex)
zend_generator * generator
function(EX_VAR(opline->result.var))
#define ZEND_GENERATOR_RETURN
#define ZEND_DO_FCALL_BY_NAME