root/sapi/phpdbg/phpdbg_list.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PHPDBG_LIST
  2. PHPDBG_LIST
  3. PHPDBG_LIST
  4. PHPDBG_LIST
  5. phpdbg_list_file
  6. phpdbg_list_function
  7. phpdbg_list_function_byname
  8. phpdbg_compile_file
  9. phpdbg_init_compile_file
  10. phpdbg_compile_string
  11. phpdbg_free_file_source
  12. phpdbg_init_list
  13. phpdbg_list_update

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Felipe Pena <felipe@php.net>                                |
  16    | Authors: Joe Watkins <joe.watkins@live.co.uk>                        |
  17    | Authors: Bob Weinand <bwoebi@php.net>                                |
  18    +----------------------------------------------------------------------+
  19 */
  20 
  21 #include <stdio.h>
  22 #include <string.h>
  23 #include <sys/stat.h>
  24 #ifndef _WIN32
  25 #       include <sys/mman.h>
  26 #       include <unistd.h>
  27 #endif
  28 #include <fcntl.h>
  29 #include "phpdbg.h"
  30 #include "phpdbg_list.h"
  31 #include "phpdbg_utils.h"
  32 #include "phpdbg_prompt.h"
  33 #include "php_streams.h"
  34 #include "zend_exceptions.h"
  35 
  36 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
  37 
  38 #define PHPDBG_LIST_COMMAND_D(f, h, a, m, l, s, flags) \
  39         PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[12], flags)
  40 
  41 const phpdbg_command_t phpdbg_list_commands[] = {
  42         PHPDBG_LIST_COMMAND_D(lines,     "lists the specified lines",    'l', list_lines,  NULL, "l", PHPDBG_ASYNC_SAFE),
  43         PHPDBG_LIST_COMMAND_D(class,     "lists the specified class",    'c', list_class,  NULL, "s", PHPDBG_ASYNC_SAFE),
  44         PHPDBG_LIST_COMMAND_D(method,    "lists the specified method",   'm', list_method, NULL, "m", PHPDBG_ASYNC_SAFE),
  45         PHPDBG_LIST_COMMAND_D(func,      "lists the specified function", 'f', list_func,   NULL, "s", PHPDBG_ASYNC_SAFE),
  46         PHPDBG_END_COMMAND
  47 };
  48 
  49 PHPDBG_LIST(lines) /* {{{ */
  50 {
  51         if (!PHPDBG_G(exec) && !zend_is_executing()) {
  52                 phpdbg_error("inactive", "type=\"execution\"", "Not executing, and execution context not set");
  53                 return SUCCESS;
  54         }
  55 
  56         switch (param->type) {
  57                 case NUMERIC_PARAM: {
  58                         const char *char_file = phpdbg_current_file();
  59                         zend_string *file = zend_string_init(char_file, strlen(char_file), 0);
  60                         phpdbg_list_file(file, param->num < 0 ? 1 - param->num : param->num, (param->num < 0 ? param->num : 0) + zend_get_executed_lineno(), 0);
  61                         efree(file);
  62                 } break;
  63 
  64                 case FILE_PARAM: {
  65                         zend_string *file = zend_string_init(param->file.name, strlen(param->file.name), 0);
  66                         phpdbg_list_file(file, param->file.line, 0, 0);
  67                         efree(file);
  68                 } break;
  69 
  70                 phpdbg_default_switch_case();
  71         }
  72 
  73         return SUCCESS;
  74 } /* }}} */
  75 
  76 PHPDBG_LIST(func) /* {{{ */
  77 {
  78         phpdbg_list_function_byname(param->str, param->len);
  79 
  80         return SUCCESS;
  81 } /* }}} */
  82 
  83 PHPDBG_LIST(method) /* {{{ */
  84 {
  85         zend_class_entry *ce;
  86 
  87         if (phpdbg_safe_class_lookup(param->method.class, strlen(param->method.class), &ce) == SUCCESS) {
  88                 zend_function *function;
  89                 char *lcname = zend_str_tolower_dup(param->method.name, strlen(param->method.name));
  90 
  91                 if ((function = zend_hash_str_find_ptr(&ce->function_table, lcname, strlen(lcname)))) {
  92                         phpdbg_list_function(function);
  93                 } else {
  94                         phpdbg_error("list", "type=\"notfound\" method=\"%s::%s\"", "Could not find %s::%s", param->method.class, param->method.name);
  95                 }
  96 
  97                 efree(lcname);
  98         } else {
  99                 phpdbg_error("list", "type=\"notfound\" class=\"%s\"", "Could not find the class %s", param->method.class);
 100         }
 101 
 102         return SUCCESS;
 103 } /* }}} */
 104 
 105 PHPDBG_LIST(class) /* {{{ */
 106 {
 107         zend_class_entry *ce;
 108 
 109         if (phpdbg_safe_class_lookup(param->str, param->len, &ce) == SUCCESS) {
 110                 if (ce->type == ZEND_USER_CLASS) {
 111                         if (ce->info.user.filename) {
 112                                 phpdbg_list_file(ce->info.user.filename, ce->info.user.line_end - ce->info.user.line_start + 1, ce->info.user.line_start, 0);
 113                         } else {
 114                                 phpdbg_error("list", "type=\"nosource\" class=\"%s\"", "The source of the requested class (%s) cannot be found", ZSTR_VAL(ce->name));
 115                         }
 116                 } else {
 117                         phpdbg_error("list", "type=\"internalclass\" class=\"%s\"", "The class requested (%s) is not user defined", ZSTR_VAL(ce->name));
 118                 }
 119         } else {
 120                 phpdbg_error("list", "type=\"notfound\" class=\"%s\"", "The requested class (%s) could not be found", param->str);
 121         }
 122 
 123         return SUCCESS;
 124 } /* }}} */
 125 
 126 void phpdbg_list_file(zend_string *filename, uint count, int offset, uint highlight) /* {{{ */
 127 {
 128         uint line, lastline;
 129         phpdbg_file_source *data;
 130         char resolved_path_buf[MAXPATHLEN];
 131         const char *abspath;
 132 
 133         if (VCWD_REALPATH(ZSTR_VAL(filename), resolved_path_buf)) {
 134                 abspath = resolved_path_buf;
 135         } else {
 136                 abspath = ZSTR_VAL(filename);
 137         }
 138 
 139         if (!(data = zend_hash_str_find_ptr(&PHPDBG_G(file_sources), abspath, strlen(abspath)))) {
 140                 phpdbg_error("list", "type=\"unknownfile\"", "Could not find information about included file...");
 141                 return;
 142         }
 143 
 144         if (offset < 0) {
 145                 count += offset;
 146                 offset = 0;
 147         }
 148 
 149         lastline = offset + count;
 150 
 151         if (lastline > data->lines) {
 152                 lastline = data->lines;
 153         }
 154 
 155         phpdbg_xml("<list %r file=\"%s\">", ZSTR_VAL(filename));
 156 
 157         for (line = offset; line < lastline;) {
 158                 uint linestart = data->line[line++];
 159                 uint linelen = data->line[line] - linestart;
 160                 char *buffer = data->buf + linestart;
 161 
 162                 if (!highlight) {
 163                         phpdbg_write("line", "line=\"%u\" code=\"%.*s\"", " %05u: %.*s", line, linelen, buffer);
 164                 } else {
 165                         if (highlight != line) {
 166                                 phpdbg_write("line", "line=\"%u\" code=\"%.*s\"", " %05u: %.*s", line, linelen, buffer);
 167                         } else {
 168                                 phpdbg_write("line", "line=\"%u\" code=\"%.*s\" current=\"current\"", ">%05u: %.*s", line, linelen, buffer);
 169                         }
 170                 }
 171 
 172                 if (*(buffer + linelen - 1) != '\n' || !linelen) {
 173                         phpdbg_out("\n");
 174                 }
 175         }
 176 
 177         phpdbg_xml("</list>");
 178 } /* }}} */
 179 
 180 void phpdbg_list_function(const zend_function *fbc) /* {{{ */
 181 {
 182         const zend_op_array *ops;
 183 
 184         if (fbc->type != ZEND_USER_FUNCTION) {
 185                 phpdbg_error("list", "type=\"internalfunction\" function=\"%s\"", "The function requested (%s) is not user defined", ZSTR_VAL(fbc->common.function_name));
 186                 return;
 187         }
 188 
 189         ops = (zend_op_array *) fbc;
 190 
 191         phpdbg_list_file(ops->filename, ops->line_end - ops->line_start + 1, ops->line_start, 0);
 192 } /* }}} */
 193 
 194 void phpdbg_list_function_byname(const char *str, size_t len) /* {{{ */
 195 {
 196         HashTable *func_table = EG(function_table);
 197         zend_function* fbc;
 198         char *func_name = (char*) str;
 199         size_t func_name_len = len;
 200 
 201         /* search active scope if begins with period */
 202         if (func_name[0] == '.') {
 203                 if (EG(scope)) {
 204                         func_name++;
 205                         func_name_len--;
 206 
 207                         func_table = &EG(scope)->function_table;
 208                 } else {
 209                         phpdbg_error("inactive", "type=\"noclasses\"", "No active class");
 210                         return;
 211                 }
 212         } else if (!EG(function_table)) {
 213                 phpdbg_error("inactive", "type=\"function_table\"", "No function table loaded");
 214                 return;
 215         } else {
 216                 func_table = EG(function_table);
 217         }
 218 
 219         /* use lowercase names, case insensitive */
 220         func_name = zend_str_tolower_dup(func_name, func_name_len);
 221 
 222         phpdbg_try_access {
 223                 if ((fbc = zend_hash_str_find_ptr(func_table, func_name, func_name_len))) {
 224                         phpdbg_list_function(fbc);
 225                 } else {
 226                         phpdbg_error("list", "type=\"nofunction\" function=\"%s\"", "Function %s not found", func_name);
 227                 }
 228         } phpdbg_catch_access {
 229                 phpdbg_error("signalsegv", "function=\"%s\"", "Could not list function %s, invalid data source", func_name);
 230         } phpdbg_end_try_access();
 231 
 232         efree(func_name);
 233 } /* }}} */
 234 
 235 zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) {
 236         phpdbg_file_source data, *dataptr;
 237         zend_file_handle fake;
 238         zend_op_array *ret;
 239         char *filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename);
 240         uint line;
 241         char *bufptr, *endptr;
 242         char resolved_path_buf[MAXPATHLEN];
 243 
 244         if (zend_stream_fixup(file, &bufptr, &data.len) == FAILURE) {
 245                 return NULL;
 246         }
 247 
 248         data.buf = emalloc(data.len + ZEND_MMAP_AHEAD + 1);
 249         if (data.len > 0) {
 250                 memcpy(data.buf, bufptr, data.len);
 251         }
 252         memset(data.buf + data.len, 0, ZEND_MMAP_AHEAD + 1);
 253         data.filename = filename;
 254         data.line[0] = 0;
 255 
 256         memset(&fake, 0, sizeof(fake));
 257         fake.type = ZEND_HANDLE_MAPPED;
 258         fake.handle.stream.mmap.buf = data.buf;
 259         fake.handle.stream.mmap.len = data.len;
 260         fake.free_filename = 0;
 261         fake.filename = filename;
 262         fake.opened_path = file->opened_path;
 263 
 264         *(dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint) * data.len)) = data;
 265         if (VCWD_REALPATH(filename, resolved_path_buf)) {
 266                 filename = resolved_path_buf;
 267         }
 268 
 269         for (line = 0, bufptr = data.buf - 1, endptr = data.buf + data.len; ++bufptr < endptr;) {
 270                 if (*bufptr == '\n') {
 271                         dataptr->line[++line] = (uint)(bufptr - data.buf) + 1;
 272                 }
 273         }
 274         dataptr->lines = ++line;
 275         dataptr->line[line] = endptr - data.buf;
 276 
 277         ret = PHPDBG_G(compile_file)(&fake, type);
 278 
 279         if (ret == NULL) {
 280                 efree(data.buf);
 281                 efree(dataptr);
 282                 return NULL;
 283         }
 284 
 285         dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line);
 286         zend_hash_str_add_ptr(&PHPDBG_G(file_sources), filename, strlen(filename), dataptr);
 287         phpdbg_resolve_pending_file_break(filename);
 288 
 289         fake.opened_path = NULL;
 290         zend_file_handle_dtor(&fake);
 291 
 292         return ret;
 293 }
 294 
 295 zend_op_array *phpdbg_init_compile_file(zend_file_handle *file, int type) {
 296         char *filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename);
 297         char resolved_path_buf[MAXPATHLEN];
 298         zend_op_array *op_array;
 299         phpdbg_file_source *dataptr;
 300 
 301         if (VCWD_REALPATH(filename, resolved_path_buf)) {
 302                 filename = resolved_path_buf;
 303         }
 304 
 305         op_array = PHPDBG_G(init_compile_file)(file, type);
 306 
 307         if (op_array == NULL) {
 308                 return NULL;
 309         }
 310 
 311         dataptr = zend_hash_str_find_ptr(&PHPDBG_G(file_sources), filename, strlen(filename));
 312         ZEND_ASSERT(dataptr != NULL);
 313 
 314         dataptr->op_array = *op_array;
 315         if (dataptr->op_array.refcount) {
 316                 ++*dataptr->op_array.refcount;
 317         }
 318 
 319         return op_array;
 320 }
 321 
 322 zend_op_array *phpdbg_compile_string(zval *source_string, char *filename) {
 323         zend_string *fake_name;
 324         zend_op_array *op_array;
 325         phpdbg_file_source *dataptr;
 326         uint line;
 327         char *bufptr, *endptr;
 328 
 329         if (PHPDBG_G(flags) & PHPDBG_IN_EVAL) {
 330                 return PHPDBG_G(compile_string)(source_string, filename);
 331         }
 332 
 333         dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint) * Z_STRLEN_P(source_string));
 334         dataptr->buf = estrndup(Z_STRVAL_P(source_string), Z_STRLEN_P(source_string));
 335         dataptr->len = Z_STRLEN_P(source_string);
 336         dataptr->line[0] = 0;
 337         for (line = 0, bufptr = dataptr->buf - 1, endptr = dataptr->buf + dataptr->len; ++bufptr < endptr;) {
 338                 if (*bufptr == '\n') {
 339                         dataptr->line[++line] = (uint)(bufptr - dataptr->buf) + 1;
 340                 }
 341         }
 342         dataptr->lines = ++line;
 343         dataptr->line[line] = endptr - dataptr->buf;
 344 
 345         op_array = PHPDBG_G(compile_string)(source_string, filename);
 346 
 347         if (op_array == NULL) {
 348                 efree(dataptr->buf);
 349                 efree(dataptr);
 350                 return NULL;
 351         }
 352 
 353         fake_name = strpprintf(0, "%s\0%p", filename, op_array->opcodes);
 354 
 355         dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line);
 356         zend_hash_add_ptr(&PHPDBG_G(file_sources), fake_name, dataptr);
 357 
 358         dataptr->filename = estrndup(ZSTR_VAL(fake_name), ZSTR_LEN(fake_name));
 359         zend_string_release(fake_name);
 360 
 361         dataptr->op_array = *op_array;
 362         if (dataptr->op_array.refcount) {
 363                 ++*dataptr->op_array.refcount;
 364         }
 365 
 366         return op_array;
 367 }
 368 
 369 void phpdbg_free_file_source(zval *zv) {
 370         phpdbg_file_source *data = Z_PTR_P(zv);
 371 
 372         if (data->buf) {
 373                 efree(data->buf);
 374         }
 375 
 376         destroy_op_array(&data->op_array);
 377 
 378         efree(data);
 379 }
 380 
 381 void phpdbg_init_list(void) {
 382         PHPDBG_G(compile_file) = zend_compile_file;
 383         PHPDBG_G(compile_string) = zend_compile_string;
 384         zend_hash_init(&PHPDBG_G(file_sources), 1, NULL, (dtor_func_t) phpdbg_free_file_source, 0);
 385         zend_compile_file = phpdbg_compile_file;
 386         zend_compile_string = phpdbg_compile_string;
 387 }
 388 
 389 void phpdbg_list_update(void) {
 390         PHPDBG_G(init_compile_file) = zend_compile_file;
 391         zend_compile_file = phpdbg_init_compile_file;
 392 }

/* [<][>][^][v][top][bottom][index][help] */