1/* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21#include "config.h" 22#include <assert.h> 23#include "CallStack.h" 24#include "DbeSession.h" 25#include "DbeView.h" 26#include "DataObject.h" 27#include "Exp_Layout.h" 28#include "Experiment.h" 29#include "Module.h" 30#include "LoadObject.h" 31#include "Expression.h" 32#include "Function.h" 33#include "Histable.h" 34#include "Sample.h" 35#include "Table.h" 36 37////////////////////////////////////////////////////////// 38// class Expression::Context 39 40static const uint64_t INDXOBJ_EXPGRID_SHIFT = 60; 41static const uint64_t INDXOBJ_EXPID_SHIFT = 32; 42 43Expression::Context::Context (DbeView *_dbev, Experiment *_exp) 44{ 45 dbev = _dbev; 46 exp = _exp; 47 dview = NULL; 48 eventId = 0; 49} 50 51Expression::Context::Context (DbeView *_dbev, Experiment *_exp, 52 DataView *_dview, long _eventId) 53{ 54 dbev = _dbev; 55 exp = _exp; 56 dview = _dview; 57 eventId = _eventId; 58} 59 60////////////////////////////////////////////////////////// 61// class Expression 62Expression::Expression (OpCode _op, uint64_t _v) 63{ 64 op = _op; 65 v = Value (_v); 66 arg0 = NULL; 67 arg1 = NULL; 68} 69 70Expression::Expression (OpCode _op, const Expression *_arg0, 71 const Expression *_arg1) 72{ 73 op = _op; 74 v = Value (); 75 arg0 = NULL; 76 arg1 = NULL; 77 if (_arg0) 78 arg0 = _arg0->copy (); 79 if (_arg1) 80 arg1 = _arg1->copy (); 81} 82 83Expression::~Expression () 84{ 85 delete arg0; 86 delete arg1; 87} 88 89Expression::Expression (const Expression &rhs) 90{ 91 op = rhs.op; 92 arg0 = NULL; 93 arg1 = NULL; 94 v = Value (rhs.v); 95 if (rhs.arg0) 96 { 97 arg0 = rhs.arg0->copy (); 98 if (v.next) 99 { 100 assert (arg0 && v.next == &(rhs.arg0->v)); 101 v.next = &(arg0->v); 102 } 103 } 104 if (rhs.arg1) 105 arg1 = rhs.arg1->copy (); 106} 107 108Expression::Expression (const Expression *rhs) 109{ 110 arg0 = NULL; 111 arg1 = NULL; 112 copy (rhs); 113} 114 115void 116Expression::copy (const Expression *rhs) 117{ 118 op = rhs->op; 119 delete arg0; 120 delete arg1; 121 arg0 = NULL; 122 arg1 = NULL; 123 v = Value (rhs->v); 124 if (rhs->arg0) 125 { 126 arg0 = rhs->arg0->copy (); 127 if (v.next) 128 { 129 assert (arg0 && v.next == &(rhs->arg0->v)); 130 v.next = &(arg0->v); 131 } 132 } 133 if (rhs->arg1) 134 arg1 = rhs->arg1->copy (); 135} 136 137Expression & 138Expression::operator= (const Expression &rhs) 139{ 140 if (this == &rhs) 141 return *this; 142 copy (&rhs); 143 return *this; 144} 145 146bool 147Expression::getVal (int propId, Context *ctx) 148{ 149 v.val = 0; 150 v.next = NULL; 151 int origPropId = propId; 152 switch (propId) 153 { 154 default: 155 { 156 if (!ctx->dview) 157 return false; 158 PropDescr *propDscr = ctx->dview->getProp (propId); 159 if (!propDscr) 160 return false; 161 switch (propDscr->vtype) 162 { 163 case TYPE_INT32: 164 v.val = ctx->dview->getIntValue (propId, ctx->eventId); 165 break; 166 case TYPE_UINT32: 167 v.val = (uint32_t) ctx->dview->getIntValue (propId, ctx->eventId); //prevent sign extension 168 break; 169 case TYPE_INT64: 170 case TYPE_UINT64: 171 v.val = ctx->dview->getLongValue (propId, ctx->eventId); 172 break; 173 case TYPE_OBJ: 174 // YM: not sure if we should allow this 175 v.val = (long long) ctx->dview->getObjValue (propId, ctx->eventId); 176 break; 177 case TYPE_STRING: 178 case TYPE_DOUBLE: 179 default: 180 return false; // Weird, programming error? 181 } 182 break; 183 } 184 case PROP_FREQ_MHZ: 185 if (ctx->exp && ctx->exp->clock) 186 v.val = ctx->exp->clock; 187 else 188 return false; 189 break; 190 case PROP_PID: 191 if (ctx->exp == NULL) 192 return false; 193 v.val = ctx->exp->getPID (); 194 break; 195 case PROP_EXPID: 196 if (ctx->exp == NULL) 197 return false; 198 v.val = ctx->exp->getUserExpId (); 199 break; 200 case PROP_EXPID_CMP: 201 if (ctx->exp == NULL) 202 return false; 203 else 204 { 205 Experiment *exp = ctx->exp; 206 if (ctx->dbev && ctx->dbev->comparingExperiments ()) 207 exp = (Experiment *) exp->get_compare_obj (); 208 v.val = exp->getUserExpId (); 209 } 210 break; 211 case PROP_EXPGRID: 212 if (ctx->exp == NULL) 213 return false; 214 v.val = ctx->exp->groupId; 215 break; 216 case PROP_NTICK_USEC: 217 if (ctx->exp == NULL) 218 return false; 219 if (ctx->dview && ctx->dview->getProp (PROP_NTICK)) 220 v.val = ctx->dview->getIntValue (PROP_NTICK, ctx->eventId) 221 * ctx->exp->get_params ()->ptimer_usec; 222 else 223 return false; 224 break; 225 case PROP_ATSTAMP: 226 case PROP_ETSTAMP: 227 if (ctx->exp == NULL) 228 return false; 229 if (ctx->dview && ctx->dview->getProp (PROP_TSTAMP)) 230 v.val = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId); 231 else 232 return false; 233 if (propId == PROP_ATSTAMP) 234 break; // absolute time, no adjustments 235 // propId==PROP_ETSTAMP 236 // calculate relative time from start of this experiment 237 v.val -= ctx->exp->getStartTime (); 238 break; 239 case PROP_TSTAMP: 240 case PROP_TSTAMP_LO: 241 case PROP_TSTAMP_HI: 242 { 243 if (ctx->exp == NULL) 244 return false; 245 if (!(ctx->dview && ctx->dview->getProp (PROP_TSTAMP))) 246 return false; 247 hrtime_t tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId); 248 // compute relative time from start of founder experiment 249 v.val = tstamp - ctx->exp->getStartTime () 250 + ctx->exp->getRelativeStartTime (); 251 if (propId == PROP_TSTAMP) 252 break; 253 if (ctx->dview->getProp (PROP_EVT_TIME)) 254 { 255 hrtime_t delta = ctx->dview->getLongValue (PROP_EVT_TIME, ctx->eventId); 256 if (propId == PROP_TSTAMP_LO) 257 { 258 if (delta > 0) 259 { // positive delta means TSTAMP is at end 260 // TSTAMP_LO = TSTAMP-delta 261 v.val -= delta; 262 break; 263 } 264 break; 265 } 266 else 267 { // PROP_TSTAMP_HI 268 if (delta < 0) 269 { // negative delta means TSTAMP is at start 270 // TSTAMP_HI = TSTAMP+(-delta) 271 v.val -= delta; 272 break; 273 } 274 break; 275 } 276 } 277 else if (ctx->dview->getProp (PROP_TSTAMP2)) 278 { 279 if (propId == PROP_TSTAMP_HI) 280 { 281 hrtime_t tstamp2 = ctx->dview->getLongValue (PROP_TSTAMP2, 282 ctx->eventId); 283 if (tstamp2 == 0) 284 break; // if not initialized, event does not have duration 285 if (tstamp2 == MAX_TIME) 286 tstamp2 = ctx->exp->getLastEvent (); 287 hrtime_t delta = tstamp2 - tstamp; 288 if (delta >= 0) 289 { 290 v.val += delta; 291 break; 292 } 293 break; // weird, delta should not be negative 294 } 295 break; // PROP_TSTAMP_LO, no modification needed 296 } 297 break; // should never be hit 298 } 299 case PROP_IOHEAPBYTES: 300 { 301 propId = PROP_IONBYTE; 302 if (ctx->dview == NULL) 303 return false; 304 if (!ctx->dview->getProp (propId)) 305 { // has property? 306 propId = PROP_HSIZE; 307 if (!ctx->dview->getProp (propId)) 308 return false; 309 } 310 v.val = ctx->dview->getLongValue (propId, ctx->eventId); 311 break; 312 } 313 case PROP_SAMPLE_MAP: 314 { 315 if (ctx->exp == NULL) 316 return false; 317 if (ctx->dview == NULL) 318 return false; 319 if (ctx->dview->getProp (PROP_SAMPLE)) 320 v.val = ctx->dview->getIntValue (PROP_SAMPLE, ctx->eventId); 321 else 322 { // does not have property, convert to time. 323 uint64_t tstamp; 324 tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId); 325 Sample *sample = ctx->exp->map_event_to_Sample (tstamp); 326 v.val = sample ? sample->get_number () : -1; 327 } 328 break; 329 } 330 case PROP_GCEVENT_MAP: 331 { 332 if (ctx->exp == NULL) 333 return false; 334 if (ctx->dview == NULL) 335 return false; 336 if (ctx->dview->getProp (PROP_GCEVENT)) 337 v.val = ctx->dview->getIntValue (PROP_GCEVENT, ctx->eventId); 338 else 339 { // does not have property, convert to time. 340 uint64_t tstamp; 341 tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId); 342 GCEvent *gcevent = ctx->exp->map_event_to_GCEvent (tstamp); 343 v.val = gcevent ? gcevent->id : 0; 344 } 345 break; 346 } 347 case PROP_LEAF: 348 { 349 if (ctx->dview == NULL) 350 return false; 351 VMode vmode = ctx->dbev ? ctx->dbev->get_view_mode () : VMODE_USER; 352 int prop_id; 353 if (vmode == VMODE_MACHINE) 354 prop_id = PROP_MSTACK; 355 else if (vmode == VMODE_EXPERT) 356 prop_id = PROP_XSTACK; 357 else 358 prop_id = PROP_USTACK; 359 if (!ctx->dview->getProp (prop_id)) 360 return false; 361 Histable *obj = CallStack::getStackPC (ctx->dview->getObjValue (prop_id, ctx->eventId), 0); 362 Function *func = (Function*) obj->convertto (Histable::FUNCTION); 363 v.val = func->id; // LEAF 364 break; 365 } 366 case PROP_STACKID: 367 { 368 VMode vmode = ctx->dbev ? ctx->dbev->get_view_mode () : VMODE_USER; 369 if (vmode == VMODE_MACHINE) 370 propId = PROP_MSTACK; 371 else if (vmode == VMODE_EXPERT) 372 propId = PROP_XSTACK; 373 else 374 propId = PROP_USTACK; 375 if (ctx->dview == NULL) 376 return false; 377 if (!ctx->dview->getProp (propId)) 378 return false; 379 v.val = (long) ctx->dview->getObjValue (propId, ctx->eventId); 380 break; 381 } 382 case PROP_STACKL: 383 case PROP_STACKI: 384 case PROP_STACK: 385 { 386 VMode vmode = ctx->dbev ? ctx->dbev->get_view_mode () : VMODE_USER; 387 if (vmode == VMODE_MACHINE) 388 propId = PROP_MSTACK; 389 else if (vmode == VMODE_EXPERT) 390 propId = PROP_XSTACK; 391 else 392 propId = PROP_USTACK; 393 } 394 // no break; 395 case PROP_MSTACKL: 396 case PROP_XSTACKL: 397 case PROP_USTACKL: 398 case PROP_MSTACKI: 399 case PROP_XSTACKI: 400 case PROP_USTACKI: 401 switch (propId) 402 { 403 case PROP_MSTACKL: 404 case PROP_MSTACKI: 405 propId = PROP_MSTACK; 406 break; 407 case PROP_XSTACKL: 408 case PROP_XSTACKI: 409 propId = PROP_XSTACK; 410 break; 411 case PROP_USTACKL: 412 case PROP_USTACKI: 413 propId = PROP_USTACK; 414 break; 415 default: 416 break; 417 } 418 // no break; 419 case PROP_MSTACK: 420 case PROP_XSTACK: 421 case PROP_USTACK: 422 { 423 if (ctx->dview == NULL) 424 return false; 425 if (!ctx->dview->getProp (propId)) 426 return false; 427 bool hide_mode = !ctx->dbev->isShowAll () 428 || ctx->dbev->isFilterHideMode (); 429 Expression *cur = this; 430 for (CallStackNode *stack = (CallStackNode *) 431 ctx->dview->getObjValue (propId, ctx->eventId); 432 stack; stack = stack->get_ancestor ()) 433 { 434 Histable *hist = stack->get_instr (); 435 if (origPropId == PROP_STACK || origPropId == PROP_MSTACK 436 || origPropId == PROP_XSTACK || origPropId == PROP_USTACK) 437 { 438 cur->v.val = hist->convertto (Histable::FUNCTION)->id; 439 cur->v.fn = cur->v.val; 440 } 441 else if (origPropId == PROP_STACKL || origPropId == PROP_MSTACKL 442 || origPropId == PROP_XSTACKL || origPropId == PROP_USTACKL) 443 { 444 cur->v.val = hist->convertto (Histable::LINE)->id; 445 if (hide_mode) 446 cur->v.fn = hist->convertto (Histable::FUNCTION)->id; 447 else 448 cur->v.fn = 0; 449 } 450 else if (origPropId == PROP_STACKI || origPropId == PROP_MSTACKI 451 || origPropId == PROP_XSTACKI || origPropId == PROP_USTACKI) 452 { 453 cur->v.val = hist->convertto (Histable::INSTR)->id; 454 if (hide_mode) 455 cur->v.fn = hist->convertto (Histable::FUNCTION)->id; 456 else 457 cur->v.fn = 0; 458 } 459 if (cur->arg1 == NULL) 460 cur->arg1 = new Expression (OP_NONE, (uint64_t) 0); 461 if (stack->get_ancestor () == NULL) 462 { 463 if (origPropId == PROP_STACKL || origPropId == PROP_MSTACKL 464 || origPropId == PROP_XSTACKL || origPropId == PROP_USTACKL 465 || origPropId == PROP_STACKI || origPropId == PROP_MSTACKI 466 || origPropId == PROP_XSTACKI || origPropId == PROP_USTACKI) 467 { 468 cur->v.next = NULL; 469 continue; 470 } 471 } 472 cur->v.next = &cur->arg1->v; 473 cur = cur->arg1; 474 } 475 if (origPropId == PROP_STACK || origPropId == PROP_MSTACK 476 || origPropId == PROP_XSTACK || origPropId == PROP_USTACK) 477 { 478 cur->v.val = dbeSession->get_Total_Function ()->id; 479 cur->v.fn = cur->v.val; 480 cur->v.next = NULL; 481 } 482 break; 483 } 484 case PROP_DOBJ: 485 { 486 if (ctx->dview == NULL) 487 return false; 488 if (!ctx->dview->getProp (PROP_DOBJ)) 489 return false; 490 DataObject *dobj = (DataObject*) 491 ctx->dview->getObjValue (PROP_DOBJ, ctx->eventId); 492 if (dobj != NULL) 493 { 494 Expression *cur = this; 495 for (;;) 496 { 497 cur->v.val = dobj->id; 498 dobj = dobj->parent; 499 if (dobj == NULL) 500 break; 501 if (cur->arg1 == NULL) 502 cur->arg1 = new Expression (OP_NONE, (uint64_t) 0); 503 cur->v.next = &cur->arg1->v; 504 cur = cur->arg1; 505 } 506 cur->v.next = NULL; 507 } 508 break; 509 } 510 case PROP_CPRID: 511 case PROP_TSKID: 512 { 513 if (ctx->dview == NULL) 514 return false; 515 if (!ctx->dview->getProp (propId)) 516 return false; 517 CallStackNode *ompstack = (CallStackNode *) 518 ctx->dview->getObjValue (propId, ctx->eventId); 519 Histable *hobj = ompstack->get_instr (); 520 if (hobj != NULL) 521 v.val = hobj->id; 522 break; 523 } 524 case PROP_JTHREAD: 525 { 526 if (ctx->exp == NULL) 527 return false; 528 if (ctx->dview == NULL) 529 return false; 530 if (!ctx->dview->getProp (propId)) 531 return false; 532 uint64_t tstamp; 533 tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId); 534 uint32_t thrid; 535 uint64_t jthr_id = 0; 536 thrid = ctx->dview->getIntValue (PROP_THRID, ctx->eventId); 537 JThread *jthread = ctx->exp->map_pckt_to_Jthread (thrid, tstamp); 538 if (jthread != JTHREAD_NONE && jthread != JTHREAD_DEFAULT) 539 { 540 jthr_id = jthread->jthr_id; 541 uint64_t grid = ctx->exp->groupId; 542 uint64_t expid = ctx->exp->getUserExpId (); 543 v.val = (grid << INDXOBJ_EXPGRID_SHIFT) | 544 (expid << INDXOBJ_EXPID_SHIFT) | jthr_id; 545 } 546 break; 547 } 548 } 549 return true; 550} 551 552bool 553Expression::bEval (Context *ctx) 554{ 555 uint64_t v0, v1; 556 switch (op) 557 { 558 case OP_DEG: 559 if (!arg1->bEval (ctx)) 560 return false; 561 if (arg1->v.val < 0) 562 { 563 v.val = 0; 564 return true; 565 } 566 if (!arg0->bEval (ctx)) 567 { 568 return false; 569 } 570 v0 = arg0->v.val; 571 v1 = arg1->v.val; 572 for (v.val = 1; v1 > 0; v1--) 573 v.val *= v0; 574 return true; 575 case OP_MUL: 576 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 577 { 578 v.val = arg0->v.val * arg1->v.val; 579 return true; 580 } 581 return false; 582 case OP_DIV: 583 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 584 { 585 v1 = arg1->v.val; 586 v.val = (v1 == 0) ? 0 : (arg0->v.val / v1); 587 return true; 588 } 589 return false; 590 case OP_REM: 591 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 592 { 593 v1 = arg1->v.val; 594 v.val = (v1 == 0) ? 0 : (arg0->v.val % v1); 595 return true; 596 } 597 return false; 598 case OP_ADD: 599 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 600 { 601 v.val = arg0->v.val + arg1->v.val; 602 // DBFIXME LIBRARY VISIBILITY 603 // hack to pass v.fn value to new expression for leaf filters USTACK+0 604 v.fn = arg0->v.fn + arg1->v.fn; 605 return true; 606 } 607 return false; 608 case OP_MINUS: 609 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 610 { 611 v.val = arg0->v.val - arg1->v.val; 612 return true; 613 } 614 return false; 615 case OP_LS: 616 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 617 { 618 v.val = arg0->v.val << arg1->v.val; 619 return true; 620 } 621 return false; 622 case OP_RS: 623 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 624 { 625 v.val = arg0->v.val >> arg1->v.val; 626 return true; 627 } 628 return false; 629 case OP_LT: 630 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 631 { 632 v.val = arg0->v.val < arg1->v.val ? 1 : 0; 633 return true; 634 } 635 return false; 636 case OP_LE: 637 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 638 { 639 v.val = arg0->v.val <= arg1->v.val ? 1 : 0; 640 return true; 641 } 642 return false; 643 case OP_GT: 644 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 645 { 646 v.val = arg0->v.val > arg1->v.val ? 1 : 0; 647 return true; 648 } 649 return false; 650 case OP_GE: 651 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 652 { 653 v.val = arg0->v.val >= arg1->v.val ? 1 : 0; 654 return true; 655 } 656 return false; 657 case OP_EQ: 658 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 659 { 660 v.val = arg0->v.val == arg1->v.val ? 1 : 0; 661 return true; 662 } 663 return false; 664 case OP_NE: 665 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 666 { 667 v.val = arg0->v.val != arg1->v.val ? 1 : 0; 668 return true; 669 } 670 return false; 671 case OP_BITAND: 672 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 673 { 674 v.val = arg0->v.val & arg1->v.val; 675 return true; 676 } 677 return false; 678 case OP_BITXOR: 679 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 680 { 681 v.val = arg0->v.val ^ arg1->v.val; 682 return true; 683 } 684 return false; 685 case OP_BITOR: 686 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 687 { 688 v.val = arg0->v.val | arg1->v.val; 689 return true; 690 } 691 return false; 692 case OP_AND: 693 if (arg0->bEval (ctx)) 694 { 695 if (arg0->v.val == 0) 696 { 697 v.val = 0; 698 return true; 699 } 700 if (arg1->bEval (ctx)) 701 { 702 v.val = arg1->v.val == 0 ? 0 : 1; 703 return true; 704 } 705 return false; 706 } 707 if (arg1->bEval (ctx) && arg1->v.val == 0) 708 { 709 v.val = 0; 710 return true; 711 } 712 return false; 713 case OP_OR: 714 if (arg0->bEval (ctx)) 715 { 716 if (arg0->v.val != 0) 717 { 718 v.val = 1; 719 return true; 720 } 721 if (arg1->bEval (ctx)) 722 { 723 v.val = arg1->v.val == 0 ? 0 : 1; 724 return true; 725 } 726 return false; 727 } 728 if (arg1->bEval (ctx) && arg1->v.val != 0) 729 { 730 v.val = 1; 731 return true; 732 } 733 return false; 734 case OP_NEQV: 735 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 736 { 737 v0 = arg0->v.val; 738 v1 = arg1->v.val; 739 v.val = (v0 == 0 && v1 != 0) || (v0 != 0 && v1 == 0) ? 1 : 0; 740 return true; 741 } 742 return false; 743 case OP_EQV: 744 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 745 { 746 v0 = arg0->v.val; 747 v1 = arg1->v.val; 748 v.val = (v0 == 0 && v1 == 0) || (v0 != 0 && v1 != 0) ? 1 : 0; 749 return true; 750 } 751 return false; 752 case OP_QWE: 753 if (arg0->bEval (ctx)) 754 { 755 if (arg0->v.val != 0) 756 { 757 if (arg1->arg0->bEval (ctx)) 758 { 759 v.val = arg1->arg0->v.val; 760 return true; 761 } 762 } 763 else 764 { 765 if (arg1->arg1->bEval (ctx)) 766 { 767 v.val = arg1->arg1->v.val; 768 return true; 769 } 770 } 771 } 772 return false; 773 case OP_COMMA: 774 if (arg0->bEval (ctx)) 775 { 776 v.next = &arg0->v; 777 if (arg1->bEval (ctx)) 778 { 779 v.val = arg1->v.val; 780 return true; 781 } 782 } 783 return false; 784 case OP_IN: 785 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 786 { 787 for (Value *s = &arg0->v; s; s = s->next) 788 { 789 bool found = false; 790 for (Value *t = &arg1->v; t; t = t->next) 791 { 792 if (t->val == s->val) 793 { 794 found = true; 795 break; 796 } 797 } 798 if (!found) 799 { 800 v.val = 0; 801 return true; 802 } 803 } 804 v.val = 1; 805 return true; 806 } 807 return false; 808 case OP_SOMEIN: 809 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 810 { 811 for (Value *s = &arg0->v; s; s = s->next) 812 { 813 for (Value *t = &arg1->v; t; t = t->next) 814 { 815 if (t->val == s->val) 816 { 817 v.val = 1; 818 return true; 819 } 820 } 821 } 822 v.val = 0; 823 return true; 824 } 825 return false; 826 case OP_ORDRIN: 827 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 828 { 829 for (Value *t0 = &arg1->v; t0; t0 = t0->next) 830 { 831 bool found = true; 832 for (Value *s = &arg0->v, *t = t0; s; s = s->next, t = t->next) 833 { 834 if (t == NULL || t->val != s->val) 835 { 836 found = false; 837 break; 838 } 839 } 840 if (found) 841 { 842 v.val = 1; 843 return true; 844 } 845 } 846 v.val = 0; 847 return true; 848 } 849 return false; 850 // LIBRARY_VISIBILITY 851 case OP_LIBRARY_IN: 852 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 853 { 854 for (Value *s = &arg0->v; s; s = s->next) 855 { 856 bool found = false; 857 uint64_t objId = s->val; 858 Histable *obj = dbeSession->findObjectById (objId); 859 bool libraryFound = false; 860 Function *fn; 861 if (obj != NULL && obj->get_type () == Histable::FUNCTION) 862 { 863 fn = (Function *) obj; 864 if (fn->isHideFunc) 865 // this belongss to a loadobject in hide/library mode 866 libraryFound = true; 867 } 868 869 if (libraryFound) 870 { 871 uint64_t lo_id = fn->module->loadobject->id; 872 for (Value *t = &arg1->v; t; t = t->next) 873 { 874 uint64_t t_id = t->fn; 875 Histable *obj2 = dbeSession->findObjectById (t_id); 876 if (obj2 != NULL 877 && obj2->get_type () == Histable::FUNCTION) 878 { 879 Function *func2 = (Function *) obj2; 880 uint64_t lo_id2 = func2->module->loadobject->id; 881 if (lo_id2 == lo_id) 882 { 883 found = true; 884 break; 885 } 886 } 887 } 888 } 889 else 890 { 891 // Not a loadobject 892 for (Value *t = &arg1->v; t; t = t->next) 893 { 894 if (t->val == s->val) 895 { 896 found = true; 897 break; 898 } 899 } 900 } 901 if (!found) 902 { 903 v.val = 0; 904 return true; 905 } 906 } 907 v.val = 1; 908 return true; 909 } 910 return false; 911 case OP_LIBRARY_SOMEIN: 912 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 913 { 914 for (Value *s = &arg0->v; s; s = s->next) 915 { 916 uint64_t objId = s->val; 917 Histable *obj = dbeSession->findObjectById (objId); 918 bool libraryFound = false; 919 Function *fn; 920 if (obj != NULL && obj->get_type () == Histable::FUNCTION) 921 { 922 fn = (Function *) obj; 923 if (fn->isHideFunc) 924 // this belongs to a loadobject in hide/library mode 925 libraryFound = true; 926 } 927 928 if (libraryFound) 929 { 930 uint64_t lo_id = fn->module->loadobject->id; 931 for (Value *t = &arg1->v; t; t = t->next) 932 { 933 uint64_t t_id = t->fn; 934 Histable *obj2 = dbeSession->findObjectById (t_id); 935 if (obj2 != NULL && obj2->get_type () == Histable::FUNCTION) 936 { 937 Function *func2 = (Function *) obj2; 938 uint64_t lo_id2 = func2->module->loadobject->id; 939 if (lo_id2 == lo_id) 940 { 941 v.val = 1; 942 return true; 943 } 944 } 945 } 946 } 947 else 948 { 949 for (Value *t = &arg1->v; t; t = t->next) 950 if (t->val == s->val) 951 { 952 v.val = 1; 953 return true; 954 } 955 } 956 } 957 v.val = 0; 958 return true; 959 } 960 return false; 961 case OP_LIBRARY_ORDRIN: 962 if (arg0->bEval (ctx) && arg1->bEval (ctx)) 963 { 964 for (Value *t0 = &arg1->v; t0; t0 = t0->next) 965 { 966 bool found = true; 967 Value *t = t0; 968 for (Value *s = &arg0->v; s; s = s->next) 969 { 970 // start comparing s->val with t->val 971 // if matches move on to s->next and t->next 972 uint64_t objId = s->val; 973 Histable *obj = dbeSession->findObjectById (objId); 974 bool libraryFound = false; 975 Function *fn; 976 if (obj != NULL && obj->get_type () == Histable::FUNCTION) 977 { 978 fn = (Function *) obj; 979 if (fn->isHideFunc) 980 libraryFound = true; 981 } 982 if (libraryFound) 983 { 984 // s->val is from a loadobject 985 // check if t->val is a func whose loadobject matches s->val 986 uint64_t lo_id = fn->module->loadobject->id; 987 uint64_t t_id = t->fn; 988 Histable *obj2 = dbeSession->findObjectById (t_id); 989 if (obj2 != NULL 990 && obj2->get_type () == Histable::FUNCTION) 991 { 992 Function *func2 = (Function *) obj2; 993 uint64_t lo_id2 = func2->module->loadobject->id; 994 if (lo_id2 != lo_id) 995 { 996 // no match 997 found = false; 998 break; 999 } 1000 else 1001 { 1002 // t->val is a func whose loadobject matches s->val 1003 while (t != NULL && lo_id2 == lo_id) 1004 { 1005 // skip frames with same load object 1006 t = t->next; 1007 t_id = t->fn; 1008 obj2 = dbeSession->findObjectById (t_id); 1009 if (obj2 != NULL 1010 && obj2->get_type () == Histable::FUNCTION) 1011 { 1012 func2 = (Function *) obj2; 1013 lo_id2 = func2->module->loadobject->id; 1014 } 1015 } 1016 } 1017 } 1018 } 1019 else 1020 { 1021 if (t == NULL || t->val != s->val) 1022 { 1023 found = false; 1024 break; 1025 } 1026 t = t->next; 1027 } 1028 } 1029 if (found) 1030 { 1031 v.val = 1; 1032 return true; 1033 } 1034 } 1035 v.val = 0; 1036 return true; 1037 } 1038 return false; 1039 case OP_BITNOT: 1040 if (arg0->bEval (ctx)) 1041 { 1042 v.val = ~arg0->v.val; 1043 return true; 1044 } 1045 return false; 1046 case OP_NOT: 1047 if (arg0->bEval (ctx)) 1048 { 1049 v.val = !arg0->v.val; 1050 return true; 1051 } 1052 return false; 1053 case OP_NUM: 1054 return true; 1055 case OP_NAME: 1056 if (ctx && arg0->bEval (ctx) && getVal ((int) arg0->v.val, ctx)) 1057 return true; 1058 return false; 1059 case OP_FUNC: 1060 // FNAME is completely processed by pEval for now 1061 v.val = 0; 1062 return true; 1063 case OP_HASPROP: 1064 if (!ctx || !ctx->dview) 1065 return false; // can't be resolved (occurs during pEval() ) 1066 else if (arg0->op != OP_NAME || !arg0->arg0) 1067 return false; // weird, wrong arg type 1068 else 1069 { 1070 int propId = (int) arg0->arg0->v.val; 1071 if (ctx->dview->getProp (propId)) 1072 v.val = 1; 1073 else 1074 v.val = 0; 1075 return true; 1076 } 1077 case OP_FILE: 1078 // FILENAME is completely processed by pEval for now 1079 v.val = 0; 1080 return true; 1081 case OP_JAVA: 1082 //JGROUP & JPARENT is completely processed by pEval for now 1083 v.val = 0; 1084 return true; 1085 case OP_COLON: 1086 return false; // OK for arg1 of OP_QWE 1087 default: 1088#ifdef IPC_LOG 1089 fprintf (stderr, "INTERNAL ERROR: Expression::eval op=%d\n", op); 1090#endif 1091 return false; 1092 } 1093 return false; 1094} 1095 1096Expression * 1097Expression::pEval (Context *ctx) // partial evaluation (dview may be NULL) 1098{ 1099 Expression *res = NULL; 1100 switch (op) 1101 { 1102 case OP_FUNC: 1103 { 1104 Vector<Histable*> *objs = NULL; 1105 if (arg0->v.val == FUNC_FNAME) 1106 { 1107 Histable::NameFormat nfmt = ctx ? ctx->dbev->get_name_format () : Histable::NA; 1108 objs = (Vector<Histable*>*)dbeSession->match_func_names ((char*) arg1->v.val, nfmt); 1109 } 1110 else if (arg0->v.val == FUNC_DNAME) 1111 objs = (Vector<Histable*>*)dbeSession->match_dobj_names ((char*) arg1->v.val); 1112 Expression *cur = new Expression (Expression::OP_NUM, (uint64_t) 0); 1113 res = cur; 1114 int i = objs ? objs->size () - 1 : -1; 1115 for (; i >= 0; i--) 1116 { 1117 cur->v.val = objs->fetch (i)->id; 1118 if (i == 0) 1119 break; 1120 cur->arg0 = new Expression (OP_NONE, (uint64_t) 0); 1121 cur->v.next = &cur->arg0->v; 1122 cur = cur->arg0; 1123 } 1124 cur->v.next = NULL; 1125 if (objs) 1126 delete objs; 1127 break; 1128 } 1129 case OP_JAVA: 1130 { 1131 Vector<JThread*> *objs = NULL; 1132 Vector<uint64_t> *grids = NULL; 1133 Vector<uint64_t> *expids = NULL; 1134 if (arg0->v.val == JAVA_JGROUP) 1135 objs = dbeSession->match_java_threads ((char*) arg1->v.val, 0, grids, 1136 expids); 1137 else if (arg0->v.val == JAVA_JPARENT) 1138 objs = dbeSession->match_java_threads ((char*) arg1->v.val, 1, grids, 1139 expids); 1140 Expression *cur = new Expression (Expression::OP_NUM, (uint64_t) 0); 1141 res = cur; 1142 int i = objs ? objs->size () - 1 : -1; 1143 for (; i >= 0; i--) 1144 { 1145 uint64_t jthr_id = 0; 1146 JThread *jthread = (JThread *) (objs->fetch (i)); 1147 jthr_id = jthread->jthr_id; 1148 uint64_t grid = grids->fetch (i); 1149 uint64_t expid = expids->fetch (i); 1150 cur->v.val = (grid << INDXOBJ_EXPGRID_SHIFT) | 1151 (expid << INDXOBJ_EXPID_SHIFT) | jthr_id; 1152 if (i == 0) 1153 break; 1154 cur->arg0 = new Expression (OP_NONE, (uint64_t) 0); 1155 cur->v.next = &cur->arg0->v; 1156 cur = cur->arg0; 1157 } 1158 cur->v.next = NULL; 1159 delete objs; 1160 delete grids; 1161 delete expids; 1162 break; 1163 } 1164 case OP_FILE: 1165 { 1166 Vector<Histable*> *objs = NULL; 1167 Histable::NameFormat nfmt = ctx ? ctx->dbev->get_name_format () : Histable::NA; 1168 if (ctx) 1169 objs = (Vector<Histable*>*)dbeSession->match_file_names ((char*) arg1->v.val, nfmt); 1170 Expression *cur = new Expression (Expression::OP_NUM, (uint64_t) 0); 1171 res = cur; 1172 int i = objs ? objs->size () - 1 : -1; 1173 for (; i >= 0; i--) 1174 { 1175 cur->v.val = objs->fetch (i)->id; 1176 if (i == 0) 1177 break; 1178 cur->arg0 = new Expression (OP_NONE, (uint64_t) 0); 1179 cur->v.next = &cur->arg0->v; 1180 cur = cur->arg0; 1181 } 1182 cur->v.next = NULL; 1183 if (objs) 1184 delete objs; 1185 break; 1186 } 1187 case OP_NUM: 1188 case OP_COMMA: 1189 res = copy (); 1190 break; 1191 case OP_IN: 1192 case OP_SOMEIN: 1193 case OP_ORDRIN: 1194 { 1195 // LIBRARY_VISIBILITY: 1196 // Evaluate the arg0 of OP_IN, OP_SOMEIN, OP_ORDRIN to see if it has any library/loadobject 1197 // Change it to OP_LIBRARY_IN, OP_LIBRARY_SOMEIN or OP_LIBRARY_ORDRIN respectively 1198 if (dbeSession->is_lib_visibility_used () && (arg0->hasLoadObject () 1199 || arg1->hasLoadObject ())) 1200 { 1201 OpCode new_op; 1202 switch (op) 1203 { 1204 case OP_IN: 1205 new_op = OP_LIBRARY_IN; 1206 break; 1207 case OP_SOMEIN: 1208 new_op = OP_LIBRARY_SOMEIN; 1209 break; 1210 case OP_ORDRIN: 1211 new_op = OP_LIBRARY_ORDRIN; 1212 break; 1213 default: 1214 new_op = op; // Should never reach here 1215 break; 1216 } 1217 if (arg1->hasLoadObject ()) 1218 res = new Expression (new_op, arg1 ? arg1->pEval (ctx) : NULL, 1219 arg0 ? arg0->pEval (ctx) : NULL); 1220 else 1221 res = new Expression (new_op, arg0 ? arg0->pEval (ctx) : NULL, 1222 arg1 ? arg1->pEval (ctx) : NULL); 1223 res->v = v; 1224 ctx->dbev->setFilterHideMode (); 1225 return res; 1226 } 1227 } 1228 // no break; if no loadobjects found fall thru to the default case 1229 default: 1230 if (bEval (ctx)) 1231 { 1232 res = new Expression (OP_NUM, v.val); 1233 break; 1234 } 1235 res = new Expression (op, arg0 ? arg0->pEval (ctx) : NULL, 1236 arg1 ? arg1->pEval (ctx) : NULL); 1237 res->v = v; 1238 break; 1239 } 1240 return res; 1241} 1242 1243bool 1244Expression::verifyObjectInExpr (Histable *obj) 1245{ 1246 uint64_t id = ((uint64_t) obj->id); 1247 if (op == OP_NUM && v.val == id) 1248 return true; 1249 bool inArg0 = false; 1250 bool inArg1 = false; 1251 if (arg0 != NULL) 1252 inArg0 = arg0->verifyObjectInExpr (obj); 1253 if (inArg0) 1254 return true; 1255 if (arg1 != NULL) 1256 inArg1 = arg1->verifyObjectInExpr (obj); 1257 if (inArg1) 1258 return true; 1259 return false; 1260} 1261 1262bool 1263Expression::hasLoadObject () 1264{ 1265 if (op == OP_NUM) 1266 { 1267 uint64_t id = v.val; 1268 Histable *obj = dbeSession->findObjectById (id); 1269 if (obj != NULL && obj->get_type () == Histable::FUNCTION) 1270 { 1271 Function *func = (Function *) obj; 1272 if (func->isHideFunc) 1273 return true; 1274 } 1275 } 1276 if (arg0 && arg0->hasLoadObject ()) 1277 return true; 1278 if (arg1 && arg1->hasLoadObject ()) 1279 return true; 1280 return false; 1281} 1282