"Fossies" - the Fresh Open Source Software Archive

Member "dbg-2.15.5/dbg_bp.c" (21 Apr 2007, 11255 Bytes) of package /linux/www/old/dbg-2.15.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dbg_bp.c" see the Fossies "Dox" file reference documentation.

    1 /***************************************************************************
    2                           dbg_bp.c  -  description
    3                              -------------------
    4     begin                : Wed Sep 12 2001
    5     copyright            : (C) 2001 by Dmitri Dmitrienko
    6                          : (C) 2002, 2007 NuSphere Corp.
    7     www                  : http://dd.cron.ru
    8                          : http://www.nusphere.com/
    9     author               : written by Dmitri Dmitrienko
   10     license              : This source file is subject to version 3.0 of 
   11                            the License,  that is bundled with this package 
   12                            in the file LICENSE, and is available at through 
   13                            the world-wide-web at http://www.nusphere.com/dbg
   14  ***************************************************************************/
   15 
   16 #include "php.h"
   17 
   18 #include "php_dbg.h"
   19 #include "dbg_cmd.h"
   20 
   21 int bp_no_cmp(const void *p1, const void *p2) {
   22     int bp_no1 = ((bp_item *)  ((*(zend_llist_element **)(p1))->data)  )->bp_no;
   23     int bp_no2 = ((bp_item *)  ((*(zend_llist_element **)(p2))->data)  )->bp_no;
   24     if (bp_no1 > bp_no2) return 1;
   25         else if (bp_no1 == bp_no2) return 0;
   26     return -1;
   27 }
   28 
   29 bp_item *find_bp_item_by_no(int bp_no TSRMLS_DC1(DBG)) {
   30     LLIST_FOREACH(DBG(breakpoint_list), bp_item, {
   31         if (data->bp_no == bp_no) return data;
   32     });
   33     return NULL;    
   34 }
   35 
   36 void bp_array_free(bpl_array* arr) {
   37     if (arr->item) {
   38         efree(arr->item);
   39         arr->item = NULL;
   40     }
   41     memset(arr, 0, sizeof(*arr));
   42 }
   43 
   44 inline void bp_array_clear(bpl_array* arr) {
   45     arr->count = 0;
   46 }
   47 
   48 void bp_array_add(bpl_array* arr, bp_item* item) {
   49     if (arr->count >= arr->limit) {
   50         arr->limit += 4;
   51         arr->item = erealloc(arr->item, arr->limit * sizeof(*(arr->item)));
   52     }
   53     if (!arr->item) return;
   54     arr->item[arr->count].item = item;
   55     arr->item[arr->count].line_no = item->line_no;
   56     arr->count += 1;
   57 }
   58 
   59 int bp_array_cmp(const void *elem1, const void *elem2) {
   60     int l1 = ((bpl_arr_item *)elem1)->line_no;
   61     int l2 = ((bpl_arr_item *)elem2)->line_no;
   62     if (l1 > l2) return 1;
   63         else if (l1 == l2) return 0;
   64     return -1;
   65 }
   66 
   67 void bp_array_sort(bpl_array* arr) {
   68     if (arr->count <= 1) return;
   69     qsort(arr->item, arr->count, sizeof(*(arr->item)), bp_array_cmp);
   70 }
   71 
   72 inline int bp_array_find(bpl_array* bp_arr, int line_no, bpl_arr_item ** start_item) {
   73     int L, H, i, c, cnt, lno;
   74     bpl_arr_item *bpit, *p;
   75 
   76     *start_item = NULL;
   77     if (!bp_arr || !(bpit = bp_arr->item)) return 0;
   78     
   79     L = 0;
   80     cnt = bp_arr->count;
   81     H = cnt - 1;
   82 
   83     while (L <= H) {
   84         i = (L + H) >> 1;
   85         lno = bpit[i].line_no;
   86         if (lno < line_no) {
   87             L = i + 1;
   88         } else {
   89             H = i - 1;
   90             if (lno == line_no) {
   91                 p = &bpit[i];
   92                 while (i > 0) {
   93                     p--;i--;
   94                     if (p->line_no != line_no) {
   95                         p++;i++;
   96                         break;
   97                     }
   98                 }
   99                 *start_item = p;
  100                 c = 1;
  101                 p++;i++;
  102                 while (i < cnt && p->line_no == line_no) {
  103                     p++;i++;
  104                     c++;
  105                 }
  106                 return c;
  107             };
  108         }
  109     }
  110     return 0;
  111 }
  112 
  113 void dbg_do_resolve_bp(bp_item* bp TSRMLS_DC1(DBG)) {
  114     int mod_no;
  115     int l_no = bp->line_no;
  116     int found = 0;
  117 
  118     if (bp->mod_no == 0 && bp->mod_name != NULL) {
  119         bp->mod_no = DBG_FINDMODULE(bp->mod_name);
  120     }
  121     mod_no = bp->mod_no;
  122     if (mod_no == 0) return;
  123 
  124     LLIST_FOREACH(DBG(ctxlines_list), ctxlines_item,
  125         if (data->mod_no == mod_no && l_no >= data->start_line_no && l_no < data->start_line_no + data->lines_cnt) {
  126             DBG_TRACE(("found %d:%d:%d\n", mod_no, data->start_line_no, data->lines_cnt));
  127             found = 1;
  128             break;
  129         }
  130     );
  131     if (found) {
  132         DBG_TRACE(("resolved %d:%d\n", mod_no, l_no));
  133         bp->state &= ~BPS_UNRESOLVED;
  134     }
  135 }
  136 
  137 void dbg_resolve_bp(TSRMLS_D1(DBG)) {
  138 
  139     DBG_TRACE(("dbg_resolve_bp\n"));
  140     LLIST_FOREACH(DBG(breakpoint_list), bp_item, {
  141         if (data->state & BPS_UNRESOLVED)
  142             dbg_do_resolve_bp(data TSRMLS_CC1(DBG));
  143     });
  144 }
  145 
  146 void dbg_rebuild_bplist_mod(mod_item* mod TSRMLS_DC1(DBG)) {
  147     int mod_no = (mod) ? (mod->mod_no) : 0;
  148     if (mod_no == 0) return;
  149 
  150     bp_array_clear(&mod->bp_arr);
  151     LLIST_FOREACH(DBG(breakpoint_list), bp_item, {
  152         if (data->mod_no == mod_no && (data->state & ~BPS_UNRESOLVED)==BPS_ENABLED) {
  153             bp_array_add(&mod->bp_arr, data);
  154         }
  155     });
  156     bp_array_sort(&mod->bp_arr);
  157     DBG(breakpoint_list_inv) = 0;
  158 }
  159 
  160 void dbg_rebuild_bplist(TSRMLS_D1(DBG)) {
  161     DBG_TRACE(("dbg_rebuild_bplist()\n"));
  162     LLIST_FOREACH(DBG(breakpoint_list), bp_item, {
  163         if ((data->state & ~BPS_UNRESOLVED) == BPS_DELETED) {
  164             DBG_TRACE(("removing deleted bp.%d\n", data->bp_no));
  165             zend_llist_del_element(&DBG(breakpoint_list), data, cmpll);
  166         }
  167     });
  168     dbg_resolve_bp(TSRMLS_C1(DBG));
  169     LLIST_FOREACH(DBG(mod_list), mod_item,
  170         dbg_rebuild_bplist_mod(data TSRMLS_CC1(DBG));
  171     );
  172     bp_array_clear(&DBG(global_bp_arr));
  173     LLIST_FOREACH(DBG(breakpoint_list), bp_item, {
  174         if (data->mod_no == 0 && data->mod_name == NULL) {
  175             bp_array_add(&DBG(global_bp_arr), data);
  176         }
  177     });
  178     bp_array_sort(&DBG(global_bp_arr));
  179 }
  180 
  181 static inline int chk_hit_bp(bp_item *bpit TSRMLS_DC3(DBG, E, C)) {
  182     int is_hit = 1, is_failed, failedtocompile = 0;
  183 
  184     if (bpit->state != BPS_ENABLED) return 0;
  185 
  186     if (bpit->condition) {
  187         zval buf, *pbuf;
  188 
  189         is_hit = 0;
  190         memset(&buf, 0, sizeof(buf));
  191         Z_TYPE_P(&buf) = IS_STRING;
  192         buf.refcount++;
  193         DBG(in_eval)++;
  194         is_failed = 1;
  195         {
  196             DBG_CTX_SAVE
  197             DBG_CTX_TRY {
  198 
  199                 if (DBG(eval_error)) {
  200                     efree(DBG(eval_error));
  201                     DBG(eval_error) = NULL;
  202                 }
  203                 if (zend_eval_string(bpit->condition, &buf, "dbg_bp_condition()" TSRMLS_CC2(C, E)) == SUCCESS && !DBG(eval_error)) {
  204                     pbuf = &buf;
  205                     convert_to_boolean_ex(&pbuf);
  206                     is_hit = (*pbuf).value.lval;
  207                 }
  208             } DBG_CTX_CATCH {               
  209                 DBG_CTX_RESTORE
  210             } DBG_CTX_ENDTRY
  211         }
  212         DBG(in_eval)--;
  213     }
  214     if (is_hit) {
  215         DBG_TRACE(("bp#%d hit\n", bpit->bp_no));
  216         bpit->hitcount++;
  217         bpit->isunderhit = 1;
  218         if (bpit->hitcount <= bpit->skiphits) is_hit = 0;
  219         if (bpit->istemp) bpit->state = BPS_DELETED;
  220     }
  221     return is_hit;
  222 }
  223 
  224 inline int dbg_chk_bp_hits(TSRMLS_D2(DBG, E)) {
  225     int mod_bpcnt, i, hitc;
  226     bpl_arr_item *mod_bpit, *p;
  227     mod_item* mod = DBG(curr_mod);
  228 
  229     TSRMLS_FETCH1_NOP(C);
  230 
  231     if (!mod) return 0;
  232     mod_bpcnt = bp_array_find(&mod->bp_arr, DBG(curr_line_no), &mod_bpit);
  233     hitc = 0;
  234     for (i=0, p=mod_bpit; i<mod_bpcnt; i++,p++) {
  235         if (chk_hit_bp(p->item TSRMLS_CC3(DBG, E, C))) hitc++;
  236     }
  237     for (i=0, p=DBG(global_bp_arr).item; i<DBG(global_bp_arr).count; i++, p++) {
  238         if (chk_hit_bp(p->item TSRMLS_CC3(DBG, E, C))) hitc++;
  239     }
  240     return hitc; 
  241 }
  242 
  243 inline void dbg_reset_bp_isunderhit(TSRMLS_D1(DBG)) {
  244     LLIST_FOREACH(DBG(breakpoint_list), bp_item, {
  245         data->isunderhit = 0;
  246     });
  247 }
  248 
  249 inline void dbg_mark_del_temp_breakpoints(TSRMLS_D1(DBG)) {
  250     DBG_TRACE(("dbg_mark_del_temp_breakpoints()\n"));
  251     LLIST_FOREACH(DBG(breakpoint_list), bp_item, {
  252         if (data->istemp) {
  253             DBG_TRACE(("mark bp.%d as deleted\n",data->bp_no));
  254             data->state = BPS_DELETED;
  255             DBG(breakpoint_list_inv) = 1;
  256         }
  257     });
  258 }
  259 
  260 inline int listout_bp_item(dbg_packet *pack, bp_item *bpitem, int bp_no) {
  261     dbg_bpl_body body;
  262     if (bpitem) {
  263         body.bp_no = bp_no;
  264         body.hitcount = bpitem->hitcount;
  265         body.icondition = dbg_packet_add_string(pack, bpitem->condition);
  266         body.imod_name = dbg_packet_add_string(pack, bpitem->mod_name);
  267         body.istemp = bpitem->istemp;
  268         body.line_no = bpitem->line_no;
  269         body.mod_no = bpitem->mod_no;
  270         body.skiphits = bpitem->skiphits;
  271         body.state = bpitem->state;
  272         body.isunderhit = bpitem->isunderhit;
  273         DBG_TRACE(("list bp.%d, state=%d\n", bpitem->bp_no, bpitem->state));
  274     } else {
  275         memset(&body, 0, sizeof(body));
  276         body.bp_no = bp_no;
  277     }
  278     dbg_packet_add_frame(pack, FRAME_BPL, &body, sizeof(body));
  279     return sizeof(body);
  280 }
  281 
  282 void dbg_add_bp_reply(dbg_packet *pack TSRMLS_DC1(DBG)) {
  283     dbg_mark_del_temp_breakpoints(TSRMLS_C1(DBG));
  284     LLIST_FOREACH(DBG(breakpoint_list), bp_item, {
  285         listout_bp_item(pack, data, data->bp_no);
  286     });
  287 }
  288 
  289 
  290 typedef int (*qsort_func_t)(const void *, const void *);
  291 
  292 void dbg_llist_sort(zend_llist *l, qsort_func_t comp_func) {
  293     int list_size=0, i;
  294 
  295     zend_llist_element **elements;
  296     zend_llist_element *element, **ptr;
  297 
  298     for (element=l->head; element; element=element->next) {
  299         list_size++;
  300     }
  301 
  302     if (list_size == 0) {
  303         return;
  304     }
  305 
  306     elements = (zend_llist_element **) emalloc(list_size*sizeof(zend_llist_element *));
  307 
  308     ptr = &elements[0];
  309 
  310     for (element=l->head; element; element=element->next) {
  311         *ptr++ = element;
  312     }
  313 
  314     qsort(elements, list_size, sizeof(zend_llist_element *), (int (*)(const void *, const void *)) comp_func);
  315 
  316     l->head = elements[0];
  317     elements[0]->prev = NULL;
  318 
  319     for (i=1; i<list_size; i++) {
  320         elements[i]->prev = elements[i-1];
  321         elements[i-1]->next = elements[i];
  322     }
  323     elements[i - 1]->next = NULL;
  324     l->tail = elements[i - 1];
  325     efree(elements);
  326 }
  327 
  328 int dbg_set_breakpoint(dbg_bps_request* req, dbg_packet *pack, dbg_packet *inpack TSRMLS_DC2(DBG, E)) {
  329     bp_item *pitem = NULL, item;
  330     char *mod_name = NULL, *condition = NULL;
  331     int sz, prev_bp_no1, bp_no;
  332     /* UPDATE | DELETE */   
  333     if (req->bp_no != 0) {
  334         DBG_TRACE(("updating bp#%d, st:%d, line:%d, skip:%d\n", req->bp_no, req->state, req->line_no, req->skiphits));
  335         bp_no = req->bp_no;
  336         pitem = find_bp_item_by_no(bp_no TSRMLS_CC1(DBG));
  337         if (pitem) {            
  338             pitem->state = req->state | BPS_UNRESOLVED;
  339             if ((req->state & ~BPS_UNRESOLVED) != BPS_DELETED) {
  340                 pitem->line_no = req->line_no;
  341                 pitem->skiphits = req->skiphits;
  342                 if (pitem->condition) {
  343                     efree(pitem->condition);
  344                     pitem->condition = NULL;
  345                 }
  346                 if (dbg_packet_findstring(inpack, req->icondition , &condition, &sz)) {
  347                     pitem->condition = estrdup(condition);
  348                     DBG_TRACE(("updating condition bp#%d, cond:'%s'\n", req->bp_no, SON(condition)));
  349                 }
  350             }
  351         }
  352     } else {
  353         /* SET */
  354         if (!dbg_packet_findstring(inpack, req->icondition, &condition, &sz))
  355             condition = NULL;
  356 
  357         if (req->imod_name!=0 || req->mod_no!=0 || req->line_no!=0) {
  358             dbg_packet_findstring(inpack, req->imod_name, &mod_name, &sz);
  359 
  360             if (req->mod_no==0) { /* by mod_name */
  361                 if (mod_name==NULL || strlen(mod_name) == 0) 
  362                     return listout_bp_item(pack, NULL, 0);
  363                 req->mod_no = DBG_FINDMODULE(mod_name);
  364             }
  365 
  366             if (req->mod_no!=0) { /* by mod_no */
  367                 mod_name = dbg_mod_name_by_no(req->mod_no TSRMLS_CC1(DBG));
  368                 if (mod_name == NULL) 
  369                     return listout_bp_item(pack, NULL, 0);
  370             }
  371         }
  372 
  373 
  374         prev_bp_no1 = 1;
  375         bp_no = 1;
  376         LLIST_FOREACH(DBG(breakpoint_list), bp_item, {
  377             if (data->bp_no > prev_bp_no1) {
  378                 bp_no = prev_bp_no1;
  379                 break;
  380             }
  381             prev_bp_no1 = data->bp_no + 1;
  382             bp_no = prev_bp_no1;
  383         });
  384 
  385         DBG_TRACE(("set bp#%d mod:'%s'(%d), line:%d, cond:'%s', tmp:%d, st:%d\n", bp_no, SON(mod_name), req->mod_no, req->line_no, condition, req->istemp, req->state));
  386 
  387         item.bp_no = bp_no;
  388         item.condition = (condition && strlen(condition) > 0) ? estrdup(condition) : NULL;
  389         item.hitcount = 0;
  390         item.istemp = req->istemp;
  391         item.isunderhit = 0;
  392         item.line_no = req->line_no;
  393         item.mod_name = (mod_name && strlen(mod_name) > 0) ? estrdup(mod_name) : NULL;
  394         item.skiphits = req->skiphits;
  395         item.mod_no = req->mod_no;
  396         item.state = req->state | BPS_UNRESOLVED;       
  397         zend_llist_add_element(&DBG(breakpoint_list), &item);
  398     }
  399 
  400     DBG(breakpoint_list_inv) = 1;
  401     dbg_rebuild_bplist(TSRMLS_C1(DBG));
  402     dbg_llist_sort(&DBG(breakpoint_list), bp_no_cmp);
  403     
  404 
  405     pitem = find_bp_item_by_no(bp_no TSRMLS_CC1(DBG));
  406     return listout_bp_item(pack, pitem, bp_no);
  407 }