1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <strings.h> 29 #include <unistd.h> 30 #include <fcntl.h> 31 #include <errno.h> 32 #include <sys/types.h> 33 #include <sys/stat.h> 34 #include <sys/mman.h> 35 #include <synch.h> 36 37 #if defined(DEBUG) 38 #include <stdarg.h> 39 #endif /* !DEBUG */ 40 41 #include "iconv_tm.h" 42 #include "hash.h" 43 44 45 /* 46 * Debug 47 */ 48 #if defined(DEBUG) 49 50 static void trace_init(void); 51 static void trace_message(char *, ...); 52 53 static char trace_option[128]; 54 55 #define TRACE(c) (*(trace_option + (c & 0x007f))) 56 #define TRACE_MESSAGE(c, args) ((TRACE(c))? trace_message args: (void)0) 57 58 #else /* !DEBUG */ 59 60 #define trace_init() 61 #define TRACE() 62 #define TRACE_MESSAGE(c, args) 63 64 #endif /* !DEBUG */ 65 66 67 /* 68 * ITM reference information 69 */ 70 typedef struct _itm_ref { 71 char *name; /* ITM file name */ 72 itm_hdr_t *hdr; /* address of ITM */ 73 size_t len; /* length of ITM */ 74 } itm_ref_t; 75 76 77 /* 78 * struct _icv_state; to keep status 79 */ 80 typedef struct _icv_state { 81 struct _itm_ref *itm; /* reference to ITM */ 82 itm_hdr_t *itm_hdr; /* address of ITM */ 83 itm_tbl_hdr_t *direc; /* current direction */ 84 itm_place_t default_action; /* default action */ 85 itm_num_t *regs; /* register */ 86 itm_num_t reg_num; /* number of register */ 87 #if defined(OP_DEPTH_MAX) 88 int op_depth; /* depth of operation */ 89 #endif /* OP_DEPTH_MAX */ 90 } icv_state_t; 91 92 93 /* 94 * function prototype 95 */ 96 void * _icv_open(const char *); 97 void _icv_close(icv_state_t *); 98 size_t _icv_iconv(icv_state_t *, const unsigned char **, 99 size_t *, unsigned char **, size_t *); 100 101 static size_t map_i_f(itm_tbl_hdr_t *, 102 const unsigned char **, size_t *, 103 unsigned char **, size_t *, long); 104 static size_t map_l_f(itm_tbl_hdr_t *, 105 const unsigned char **, size_t *, 106 unsigned char **, size_t *, long); 107 static size_t map_h_l(itm_tbl_hdr_t *, 108 const unsigned char **, size_t *, 109 unsigned char **, size_t *, long); 110 static size_t map_d_e_l(itm_tbl_hdr_t *, 111 const unsigned char **, size_t *, 112 unsigned char **, size_t *, long); 113 static size_t eval_cond_tbl(icv_state_t *, itm_place_t, 114 const unsigned char **, size_t *, 115 size_t, itm_direc_t *); 116 static size_t eval_op_tbl(icv_state_t *, itm_place_t, 117 const unsigned char **, size_t *, 118 unsigned char **, size_t *); 119 static size_t eval_op(icv_state_t *, itm_place2_t, 120 const unsigned char **, size_t *, 121 unsigned char **, size_t *); 122 123 static itm_num_t eval_expr(icv_state_t *, itm_place_t, 124 size_t, const unsigned char *, size_t); 125 126 static void itm_ref_free(int, void *, void *, void *, size_t); 127 static itm_ref_t *itm_ref_inc(const char *); 128 static void itm_ref_dec(itm_ref_t *); 129 130 static void op_init_default(icv_state_t *); 131 static void op_reset_default(icv_state_t *); 132 static void regs_init(icv_state_t *); 133 134 135 /* 136 * macro definition 137 */ 138 139 #define ADDR(place) ((void *)(((char *)(ist->itm_hdr)) +\ 140 ((itm_place2_t)(place.itm_ptr)))) 141 #define ADDR2(place2) ((void *)(((char *)(ist->itm_hdr)) +\ 142 ((itm_place2_t)(place2)))) 143 #define DADDR(n) (((n)->size <= (sizeof ((n)->place.itm_64d))) ? \ 144 ((unsigned char *)(&((n)->place.itm_64d))) :\ 145 ((unsigned char *)(ADDR((n)->place)))) 146 147 #define REG(n) (*(ist->regs + (n))) 148 #define DISCARD(c) (((*inbuf) = (void *)((*inbuf) + (c))),\ 149 ((*inbytesleft) -= (c))) 150 #define GET(c) ((c) = **inbuf, (*inbuf)++, (*inbytesleft)--) 151 #define PUT(c) (**outbuf = (c), (*outbuf)++, (*outbytesleft)--) 152 153 #define RETVALERR ((size_t)(-1)) 154 #define RETVALDIR ((size_t)(-2)) 155 #define RETVALBRK ((size_t)(-3)) 156 #define RETVALRET ((size_t)(-4)) 157 158 #define UPDATE_ARGS() (*inbuf = ip, \ 159 *inbytesleft = ileft, \ 160 *outbuf = op, \ 161 *outbytesleft = oleft) 162 163 /* 164 * Open; called from iconv_open() 165 */ 166 void * 167 _icv_open(const char *itm) 168 { 169 icv_state_t *ist; 170 itm_hdr_t *hdr; 171 itm_ref_t *itm_ref; 172 int r; 173 174 /* 175 * for debug 176 */ 177 trace_init(); 178 179 /* 180 * _icv_open() primaty task 181 */ 182 itm_ref = itm_ref_inc(itm); 183 if (NULL == itm_ref) { 184 return ((void *)(-1)); 185 } 186 187 if (NULL == (ist = malloc(sizeof (icv_state_t)))) { 188 r = errno; 189 itm_ref_dec(itm_ref); 190 errno = r; 191 return (NULL); 192 } 193 194 ist->itm = itm_ref; 195 ist->itm_hdr = ist->itm->hdr; 196 ist->reg_num = ist->itm->hdr->reg_num; 197 198 hdr = ist->itm->hdr; 199 ist->direc = ADDR(hdr->direc_init_tbl); 200 ist->default_action.itm_64d = 0; 201 #if defined(OP_DEPTH_MAX) 202 ist->op_depth = 0; 203 #endif /* OP_DEPTH_MAX */ 204 205 206 /* 207 * brief sanity check 208 */ 209 if (hdr->itm_size.itm_ptr <= hdr->direc_init_tbl.itm_ptr) { 210 _icv_close(ist); 211 errno = ELIBBAD; 212 return ((void *)(-1)); 213 } 214 215 216 /* allocate register region */ 217 if (hdr->reg_num <= 0) { 218 ist->regs = NULL; 219 } else { 220 ist->regs = malloc((sizeof (itm_num_t)) * hdr->reg_num); 221 if (NULL == ist->regs) { 222 r = errno; 223 _icv_close(ist); 224 errno = r; 225 return ((void *)(-1)); 226 } 227 (void) memset(ist->regs, 0, 228 (sizeof (itm_num_t)) * hdr->reg_num); 229 } 230 231 232 /* evaluate init operation */ 233 if (0 != ist->itm_hdr->op_init_tbl.itm_ptr) { 234 const unsigned char *ip = NULL; 235 size_t ileft = 0; 236 unsigned char *op = NULL; 237 size_t oleft = 0; 238 (void) eval_op_tbl(ist, ist->itm_hdr->op_init_tbl, &ip, 239 &ileft, &op, &oleft); 240 } else { 241 op_init_default(ist); 242 } 243 244 return (ist); 245 } 246 247 248 /* 249 * Close; called from iconv_close 250 */ 251 void 252 _icv_close(icv_state_t *ist) 253 { 254 if (NULL == ist) { 255 errno = EBADF; 256 return; 257 } 258 itm_ref_dec(ist->itm); 259 free(ist->regs); 260 free(ist); 261 } 262 263 264 /* 265 * Actual conversion; called from iconv() 266 */ 267 size_t 268 _icv_iconv( 269 icv_state_t *ist, 270 const unsigned char **inbuf, 271 size_t *inbytesleft, 272 unsigned char **outbuf, 273 size_t *outbytesleft) 274 { 275 size_t retval; 276 itm_hdr_t *hdr; 277 itm_type_t type; 278 const unsigned char *ip; 279 size_t ileft; 280 itm_place_t action; 281 282 if (NULL == ist) { 283 errno = EBADF; 284 TRACE_MESSAGE('e', ("_icv_iconv: error=%d\n", errno)); 285 return ((size_t)(-1)); 286 } 287 if (NULL == inbuf) { 288 ip = NULL; 289 inbuf = &ip; 290 } 291 if (NULL == inbytesleft) { 292 ileft = 0; 293 inbytesleft = &ileft; 294 } 295 296 hdr = ist->itm_hdr; 297 298 retval = 0; 299 300 TRACE_MESSAGE('i', ("_icv_iconv(inbuf=%p inbytesleft=%ld " 301 "outbuf=%p outbytesleft=%ld)\n", (NULL == inbuf) ? 0 : *inbuf, 302 (NULL == inbytesleft) ? 0 : *inbytesleft, 303 (NULL == outbuf) ? 0 : *outbuf, 304 (NULL == outbytesleft) ? 0 : *outbytesleft)); 305 306 /* 307 * If (NULL == inbuf || NULL == *inbuf) then this conversion is 308 * placed into initial state. 309 */ 310 if ((NULL == inbuf) || (NULL == *inbuf)) { 311 if (0 != hdr->op_reset_tbl.itm_ptr) { 312 ist->direc = ADDR(hdr->direc_init_tbl); 313 retval = eval_op_tbl(ist, hdr->op_reset_tbl, inbuf, 314 inbytesleft, outbuf, outbytesleft); 315 if ((size_t)(-1) == retval) { 316 return (retval); 317 } 318 } else { 319 op_reset_default(ist); 320 } 321 return ((size_t)(0)); 322 } 323 324 if (ITM_TBL_MAP_INDEX_FIXED_1_1 == ist->direc->type) { 325 itm_map_idx_fix_hdr_t *map_hdr; 326 char *map; 327 const unsigned char *ip; 328 size_t ileft; 329 unsigned char *op; 330 size_t oleft; 331 332 map_hdr = (itm_map_idx_fix_hdr_t *)(ist->direc + 1); 333 map = (char *)(map_hdr + 1); 334 335 if (1 == map_hdr->default_error) { 336 retval = map_i_f(ist->direc, inbuf, inbytesleft, 337 outbuf, outbytesleft, 0); 338 return (retval); 339 } 340 341 ip = *inbuf; 342 ileft = *inbytesleft; 343 op = *outbuf; 344 oleft = *outbytesleft; 345 346 while (1 <= ileft) { 347 if (oleft < 1) { 348 UPDATE_ARGS(); 349 errno = E2BIG; 350 TRACE_MESSAGE('e', ("_icv_iconv: error=%d\n", 351 errno)); 352 return ((size_t)-1); 353 } 354 *(op++) = *(map + *(ip++)); 355 ileft--; 356 oleft--; 357 358 } 359 UPDATE_ARGS(); 360 return (0); 361 } else if (ITM_TBL_MAP_INDEX_FIXED == ist->direc->type) { 362 retval = map_i_f(ist->direc, inbuf, inbytesleft, 363 outbuf, outbytesleft, 0); 364 return (retval); 365 } else if (ITM_TBL_MAP_HASH == ist->direc->type) { 366 retval = map_h_l(ist->direc, inbuf, inbytesleft, 367 outbuf, outbytesleft, 0); 368 return (retval); 369 } else if (ITM_TBL_MAP_DENSE_ENC == ist->direc->type) { 370 retval = map_d_e_l(ist->direc, inbuf, inbytesleft, 371 outbuf, outbytesleft, 0); 372 return (retval); 373 } else if (ITM_TBL_MAP_LOOKUP == ist->direc->type) { 374 retval = map_l_f(ist->direc, inbuf, inbytesleft, 375 outbuf, outbytesleft, 0); 376 return (retval); 377 } 378 379 #if defined(OP_DEPTH_MAX) 380 ist->op_depth = 0; 381 #endif /* OP_DEPTH_MAX */ 382 383 384 /* 385 * Main loop; basically 1 loop per 1 output character 386 */ 387 retry_cond_eval: 388 while (0 < *inbytesleft) { 389 itm_tbl_hdr_t *direc_hdr; 390 itm_direc_t *direc; 391 long i; 392 393 direc_hdr = ist->direc; 394 direc = (itm_direc_t *)(ist->direc + 1); 395 for (i = 0; /* NULL */; i++, direc++) { 396 if (i >= direc_hdr->number) { 397 if (0 == ist->default_action.itm_ptr) { 398 errno = EILSEQ; 399 TRACE_MESSAGE('e', 400 ("_icv_iconv:error=%d\n", errno)); 401 return ((size_t)(-1)); 402 } 403 404 405 406 action = ist->default_action; 407 type = ((itm_tbl_hdr_t *)(ADDR(action)))->type; 408 TRACE_MESSAGE('E', 409 ("escape seq (default action=%6p, " 410 "type=%ld) executing\n", 411 action.itm_ptr, type)); 412 } else if (0 != direc->condition.itm_ptr) { 413 retval = eval_cond_tbl(ist, direc->condition, 414 inbuf, inbytesleft, *outbytesleft, direc); 415 if ((size_t)(0) == retval) { 416 continue; 417 } else if ((size_t)(-1) == retval) { 418 return (retval); 419 } else if ((size_t)(2) == retval) { 420 goto retry_cond_eval; 421 } 422 action = direc->action; 423 type = ((itm_tbl_hdr_t *)(ADDR(action)))->type; 424 } else { 425 action = direc->action; 426 type = ((itm_tbl_hdr_t *)(ADDR(action)))->type; 427 } 428 429 TRACE_MESSAGE('a', 430 ("inbytesleft=%ld; type=%ld:action=%p\n", 431 *inbytesleft, type, action.itm_ptr)); 432 switch (ITM_TBL_MASK & type) { 433 case ITM_TBL_OP: 434 retval = eval_op_tbl(ist, action, 435 inbuf, inbytesleft, outbuf, outbytesleft); 436 if ((size_t)(-1) == retval) { 437 return (retval); 438 } 439 break; 440 case ITM_TBL_DIREC: 441 ist->direc = ADDR(action); 442 break; 443 case ITM_TBL_MAP: 444 switch (type) { 445 case ITM_TBL_MAP_INDEX_FIXED_1_1: 446 case ITM_TBL_MAP_INDEX_FIXED: 447 retval = map_i_f(ADDR(action), 448 inbuf, inbytesleft, 449 outbuf, outbytesleft, 1); 450 break; 451 case ITM_TBL_MAP_HASH: 452 retval = map_h_l(ADDR(action), 453 inbuf, inbytesleft, 454 outbuf, outbytesleft, 1); 455 break; 456 case ITM_TBL_MAP_DENSE_ENC: 457 retval = map_d_e_l(ADDR(action), 458 inbuf, inbytesleft, 459 outbuf, outbytesleft, 1); 460 break; 461 case ITM_TBL_MAP_LOOKUP: 462 retval = map_l_f(ADDR(action), 463 inbuf, inbytesleft, 464 outbuf, outbytesleft, 1); 465 break; 466 default: 467 errno = ELIBBAD; 468 TRACE_MESSAGE('e', 469 ("_icv_iconv:error=%d\n", errno)); 470 return ((size_t)(-1)); 471 472 } 473 if ((size_t)(-1) == retval) { 474 return (retval); 475 } 476 break; 477 default: /* never */ 478 errno = ELIBBAD; 479 TRACE_MESSAGE('e', 480 ("_icv_iconv:error=%d\n", errno)); 481 return ((size_t)(-1)); 482 } 483 break; 484 } 485 } 486 return (retval); 487 } 488 489 490 491 /* 492 * map-indexed-fixed 493 */ 494 static size_t 495 map_i_f( 496 itm_tbl_hdr_t *tbl_hdr, 497 const unsigned char **inbuf, 498 size_t *inbytesleft, 499 unsigned char **outbuf, 500 size_t *outbytesleft, 501 long once) 502 { 503 itm_map_idx_fix_hdr_t *map_hdr; 504 long i; 505 unsigned char c; 506 unsigned long j; 507 const unsigned char *p; 508 509 TRACE_MESSAGE('i', ("map_i_f\n")); 510 511 map_hdr = (itm_map_idx_fix_hdr_t *)(tbl_hdr + 1); 512 513 do { 514 if (*inbytesleft < map_hdr->source_len) { 515 errno = EINVAL; 516 TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno)); 517 return ((size_t)(-1)); 518 } 519 520 j = 0; 521 for (i = 0; i < map_hdr->source_len; i++) { 522 GET(c); 523 j = ((j << 8) | c); 524 } 525 526 if (((j < map_hdr->start.itm_ptr) || 527 (map_hdr->end.itm_ptr < j)) && 528 (0 < map_hdr->default_error)) { 529 errno = EILSEQ; 530 (*inbuf) = (void*) ((*inbuf) - map_hdr->source_len); 531 (*inbytesleft) += map_hdr->source_len; 532 TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno)); 533 return ((size_t)(-1)); 534 } 535 536 if (*outbytesleft < map_hdr->result_len) { 537 errno = E2BIG; 538 (*inbuf) = (void *)((*inbuf) - map_hdr->source_len); 539 (*inbytesleft) += map_hdr->source_len; 540 TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno)); 541 return ((size_t)(-1)); 542 } 543 544 if ((j < map_hdr->start.itm_ptr) || 545 (map_hdr->end.itm_ptr < j)) { 546 if (0 == map_hdr->default_error) { 547 p = (((unsigned char *)(map_hdr + 1)) + 548 (map_hdr->result_len * (tbl_hdr->number))); 549 for (i = 0; i < map_hdr->result_len; i++) { 550 PUT(*(p + i)); 551 } 552 } else { 553 p = ((*inbuf) - map_hdr->source_len); 554 for (i = 0; i < map_hdr->source_len; i++) { 555 PUT(*(p + i)); 556 } 557 } 558 } else { 559 char *map_error; 560 map_error = (((char *)(map_hdr + 1)) + 561 (map_hdr->result_len * (tbl_hdr->number)) + 562 (j - map_hdr->start.itm_ptr)); 563 if (0 == map_hdr->default_error) { 564 map_error = (void *) 565 (map_error + map_hdr->result_len); 566 } 567 if (((1 == map_hdr->default_error) || 568 (0 < map_hdr->error_num)) && 569 (0 != *(map_error))) { 570 errno = EILSEQ; 571 (*inbuf) = (void *) 572 ((*inbuf) - map_hdr->source_len); 573 (*inbytesleft) += map_hdr->source_len; 574 TRACE_MESSAGE('e', 575 ("map_i_f:error=%d\n", errno)); 576 return ((size_t)(-1)); 577 } 578 p = (((unsigned char *)(map_hdr + 1)) + 579 (map_hdr->result_len * 580 (j - map_hdr->start.itm_ptr))); 581 for (i = 0; i < map_hdr->result_len; i++) { 582 PUT(*(p + i)); 583 } 584 } 585 } while ((0 < *inbytesleft) && (0 == once)); 586 587 return (size_t)(0); 588 } 589 590 591 /* 592 * map-lookup-fixed 593 */ 594 static size_t 595 map_l_f( 596 itm_tbl_hdr_t *tbl_hdr, 597 const unsigned char **inbuf, 598 size_t *inbytesleft, 599 unsigned char **outbuf, 600 size_t *outbytesleft, 601 long once) 602 { 603 itm_map_lookup_hdr_t *map_hdr; 604 long i; 605 unsigned char *map; 606 const unsigned char *p; 607 long high; 608 long mid; 609 long low; 610 long result; 611 itm_size_t pair_size; 612 613 TRACE_MESSAGE('i', ("map_l_f\n")); 614 615 map_hdr = (itm_map_lookup_hdr_t *)(tbl_hdr + 1); 616 map = (unsigned char *)(map_hdr + 1); 617 pair_size = map_hdr->source_len + 1 + map_hdr->result_len; 618 619 do { 620 if (*inbytesleft < map_hdr->source_len) { 621 errno = EINVAL; 622 TRACE_MESSAGE('e', ("map_l_f:error=%d\n", errno)); 623 return ((size_t)(-1)); 624 } 625 626 for (low = 0, high = tbl_hdr->number; low < high; ) { 627 mid = (low + high) / 2; 628 p = map + (pair_size * mid); 629 for (i = 0, result = 0; i < map_hdr->source_len; 630 i++, p++) { 631 if (*(unsigned char *)(*inbuf + i) < *p) { 632 result = -1; 633 break; 634 } 635 if (*p < *(unsigned char *)(*inbuf + i)) { 636 result = 1; 637 break; 638 } 639 } 640 if (result < 0) { 641 high = mid; 642 } else if (0 < result) { 643 low = mid + 1; 644 } else { /* 0 == result */ 645 break; 646 } 647 } 648 649 if (0 != result) { 650 if (map_hdr->default_error < 0) { 651 p = *inbuf; 652 } else if (0 == map_hdr->default_error) { 653 p = map + (pair_size * tbl_hdr->number) + 654 map_hdr->source_len + 1; 655 } else if (0 < map_hdr->default_error) { 656 errno = EILSEQ; 657 TRACE_MESSAGE('e', ("map_l_f:error=%d\n", 658 errno)); 659 return ((size_t)(-1)); 660 } 661 } else { 662 if (0 != (*p)) { 663 errno = EILSEQ; 664 TRACE_MESSAGE('e', ("map_l_f:error=%d\n", 665 errno)); 666 return ((size_t)(-1)); 667 } 668 p++; 669 } 670 671 if (*outbytesleft < map_hdr->result_len) { 672 errno = E2BIG; 673 TRACE_MESSAGE('e', ("map_l_f:error=%d\n", errno)); 674 return ((size_t)(-1)); 675 } 676 DISCARD(map_hdr->source_len); 677 678 for (i = 0; i < map_hdr->result_len; i++) { 679 PUT(*(p + i)); 680 } 681 } while ((0 < *inbytesleft) && (0 == once)); 682 683 return ((size_t)(0)); 684 } 685 686 687 /* 688 * map-hash-lookup 689 */ 690 static size_t 691 map_h_l( 692 itm_tbl_hdr_t *tbl_hdr, 693 const unsigned char **inbuf, 694 size_t *inbytesleft, 695 unsigned char **outbuf, 696 size_t *outbytesleft, 697 long once) 698 { 699 itm_map_hash_hdr_t *map_hdr; 700 long i; 701 unsigned char *map_error; 702 unsigned char *map_hash; 703 unsigned char *map_of; 704 const unsigned char *p; 705 const unsigned char *q; 706 long high; 707 long mid; 708 long low; 709 long result; 710 itm_size_t pair_size; 711 itm_size_t hash_value; 712 itm_size_t source_len; 713 itm_size_t result_len; 714 715 TRACE_MESSAGE('i', ("map_hash\n")); 716 717 map_hdr = (itm_map_hash_hdr_t *)(tbl_hdr + 1); 718 map_error = (unsigned char *)(map_hdr + 1); 719 map_hash = (map_error + map_hdr->hash_tbl_num); 720 map_of = map_hash + map_hdr->hash_tbl_size; 721 pair_size = map_hdr->source_len + 1 + map_hdr->result_len; 722 source_len = map_hdr->source_len; 723 result_len = map_hdr->result_len; 724 725 do { 726 if (*inbytesleft < source_len) { 727 errno = EINVAL; 728 TRACE_MESSAGE('e', ("map_h_l:error=%d\n", errno)); 729 return ((size_t)(-1)); 730 } 731 732 result = 1; 733 q = *inbuf; 734 hash_value = hash((const char *)(q), source_len, 735 map_hdr->hash_tbl_num); 736 p = map_hash + (pair_size * hash_value); 737 if (1 == *(map_error + hash_value)) { 738 for (i = 0, result = 0; i < source_len; i++) { 739 if (*(q + i) != *(p++)) { 740 result = -2; 741 break; 742 } 743 } 744 TRACE_MESSAGE('G', 745 ("(h=%d): find pair without conflict\n", 746 hash_value)); 747 } else if (0 == *(map_error + hash_value)) { 748 TRACE_MESSAGE('G', ("(h=%d): No Pair\n", hash_value)); 749 result = -3; 750 } else /* if (0 < *(map_error + hash_value)) */ { 751 for (i = 0, result = 0; i < source_len; i++) { 752 if (*(q + i) != *(p++)) { 753 result = 1; 754 break; 755 } 756 } 757 if (0 < result) { 758 for (low = 0, high = map_hdr->hash_of_num; 759 low < high; /* NOP */) { 760 mid = (low + high) / 2; 761 p = map_of + (pair_size * mid); 762 for (i = 0, result = 0; 763 i < source_len; 764 i++, p++) { 765 if (*(q + i) < *p) { 766 result = -1; 767 break; 768 } 769 if (*p < *(q + i)) { 770 result = 1; 771 break; 772 } 773 } 774 if (result < 0) { 775 high = mid; 776 } else if (0 < result) { 777 low = mid + 1; 778 } else { /* 0 == result */ 779 TRACE_MESSAGE('G', ("(h=%d): " 780 "find data on out of " 781 "hashtable with CONFLICT\n", 782 hash_value)); 783 break; 784 } 785 } 786 } 787 } 788 if (0 != result) { 789 if (map_hdr->default_error < 0) { 790 p = q; 791 } else if (0 == map_hdr->default_error) { 792 p = map_of + map_hdr->hash_of_size; 793 } else if (0 < map_hdr->default_error) { 794 TRACE_MESSAGE('G', ("(h=%d): NO PAIR\n", 795 hash_value)); 796 errno = EILSEQ; 797 TRACE_MESSAGE('e', 798 ("map_h_l:error=%d\n", errno)); 799 return ((size_t)(-1)); 800 } 801 } else { 802 if (0 != (*p)) { 803 errno = EILSEQ; 804 TRACE_MESSAGE('G', (" : error pair\n")); 805 TRACE_MESSAGE('e', ("map_l_f:error\n", errno)); 806 return ((size_t)(-1)); 807 } 808 p++; 809 } 810 811 if (*outbytesleft < result_len) { 812 errno = E2BIG; 813 TRACE_MESSAGE('e', ("map_h_l:error=%d\n", errno)); 814 return ((size_t)(-1)); 815 } 816 DISCARD(source_len); 817 818 for (i = 0; i < result_len; i++) { 819 PUT(*(p + i)); 820 } 821 } while ((0 < *inbytesleft) && (0 == once)); 822 823 return ((size_t)(0)); 824 } 825 826 827 /* 828 * map-dense_encoding-lookup 829 */ 830 static size_t 831 map_d_e_l( 832 itm_tbl_hdr_t *tbl_hdr, 833 const unsigned char **inbuf, 834 size_t *inbytesleft, 835 unsigned char **outbuf, 836 size_t *outbytesleft, 837 long once) 838 { 839 itm_map_dense_enc_hdr_t *map_hdr; 840 long i; 841 itm_num_t j; 842 const unsigned char *p; 843 unsigned char *map_ptr; 844 unsigned char *map_error; 845 unsigned char *byte_seq_min; 846 unsigned char *byte_seq_max; 847 848 TRACE_MESSAGE('i', ("map_d_e_l\n")); 849 850 map_hdr = (itm_map_dense_enc_hdr_t *)(tbl_hdr + 1); 851 map_ptr = ((unsigned char *)(map_hdr + 1) + map_hdr->source_len + 852 map_hdr->source_len); 853 map_error = (map_ptr + (tbl_hdr->number * map_hdr->result_len)); 854 if (0 == map_hdr->default_error) { 855 map_error = (void *)(map_error + map_hdr->result_len); 856 } 857 byte_seq_min = (unsigned char *)(map_hdr + 1); 858 byte_seq_max = byte_seq_min + map_hdr->source_len; 859 860 do { 861 if (*inbytesleft < map_hdr->source_len) { 862 errno = EINVAL; 863 TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno)); 864 return ((size_t)(-1)); 865 } 866 867 j = hash_dense_encoding(*inbuf, map_hdr->source_len, 868 byte_seq_min, byte_seq_max); 869 870 if (((j < 0) || (tbl_hdr->number < j)) && 871 (0 < map_hdr->default_error)) { 872 errno = EILSEQ; 873 TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno)); 874 return ((size_t)(-1)); 875 } 876 877 if (*outbytesleft < map_hdr->result_len) { 878 errno = E2BIG; 879 TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno)); 880 return ((size_t)(-1)); 881 } 882 883 if ((j < 0) || (tbl_hdr->number < j)) { 884 if (0 == map_hdr->default_error) { 885 p = (map_ptr + (tbl_hdr->number * 886 map_hdr->result_len)); 887 for (i = 0; i < map_hdr->result_len; i++) { 888 PUT(*(p + i)); 889 } 890 } else { 891 p = *inbuf; 892 for (i = 0; i < map_hdr->source_len; i++) { 893 PUT(*(p + i)); 894 } 895 } 896 } else { 897 if ((1 == map_hdr->default_error) || 898 (0 < map_hdr->error_num)) { 899 if (0 != *(map_error + j)) { 900 errno = EILSEQ; 901 TRACE_MESSAGE('e', 902 ("map_d_e_l:error=%d\n", errno)); 903 return ((size_t)(-1)); 904 } 905 } 906 p = (map_ptr + (map_hdr->result_len * j)); 907 for (i = 0; i < map_hdr->result_len; i++) { 908 PUT(*(p + i)); 909 } 910 } 911 DISCARD(map_hdr->source_len); 912 } while ((0 < *inbytesleft) && (0 == once)); 913 914 return ((size_t)(0)); 915 } 916 917 918 919 /* 920 * Evaluate condition table 921 * 922 */ 923 static size_t 924 eval_cond_tbl(icv_state_t *ist, itm_place_t cond_place, 925 const unsigned char **inbuf, size_t *inbytesleft, size_t outbytesleft, 926 itm_direc_t *direc) 927 { 928 itm_tbl_hdr_t *cond_hdr; 929 itm_cond_t *cond; 930 long i; 931 long j; 932 long k; 933 size_t retval; 934 itm_tbl_hdr_t *rth; 935 itm_range_hdr_t *rtsh; 936 unsigned char *p; 937 itm_tbl_hdr_t *eth; 938 itm_escapeseq_hdr_t *eh; 939 itm_data_t *d; 940 const unsigned char *ip; 941 size_t ileft; 942 943 retval = 0; 944 ip = *inbuf; 945 ileft = *inbytesleft; 946 cond_hdr = ADDR(cond_place); 947 cond = (itm_cond_t *)(cond_hdr + 1); 948 for (i = 0; i < cond_hdr->number; i++, cond++) { 949 switch (cond->type) { 950 case ITM_COND_BETWEEN: 951 rth = ADDR(cond->operand.place); 952 rtsh = (itm_range_hdr_t *)(rth + 1); 953 if (ileft < rtsh->len) { 954 errno = EINVAL; 955 TRACE_MESSAGE('e', ("eval_cond_tbl:error=%d\n", 956 errno)); 957 retval = ((size_t)(-1)); 958 goto eval_cond_return; 959 } 960 p = (unsigned char *)(rtsh + 1); 961 retval = 0; 962 for (j = 0; j < rth->number; 963 j++, p = (void *)(p + (2 * rtsh->len))) { 964 retval = 1; 965 for (k = 0; k < rtsh->len; k++) { 966 if ((*(ip + k) < *(p + k)) || 967 (*(p + rtsh->len + k) < 968 *(ip + k))) { 969 retval = 0; 970 break; 971 } 972 } 973 if (1 == retval) { 974 break; 975 } 976 } 977 if (0 == retval) { 978 TRACE_MESSAGE('b', 979 ("out of between (%p) len= rtsh=%ld\n", 980 *ip, rtsh->len)); 981 goto eval_cond_return; 982 } 983 break; /* continue */ 984 case ITM_COND_ESCAPESEQ: 985 /* 986 * if escape sequence occur, 987 * change ist->default_action and return 2. 988 * never return 1. 989 */ 990 retval = 0; 991 eth = ADDR(cond->operand.place); 992 eh = (itm_escapeseq_hdr_t *)(eth + 1); 993 if (0 == ist->default_action.itm_ptr) { 994 ist->default_action = direc->action; 995 TRACE_MESSAGE('E', 996 ("escape seq (default action=%6p, " 997 "type=%ld) set\n", 998 direc->action.itm_ptr, ((itm_tbl_hdr_t *) 999 (ADDR(direc->action)))->type)); 1000 } 1001 retval = 0; 1002 if (*inbytesleft < eh->len_min) { 1003 break; 1004 } 1005 for (j = 0, d = (itm_data_t *)(eh + 1); 1006 j < eth->number; 1007 j++, d++) { 1008 if (*inbytesleft < d->size) { 1009 continue; 1010 } 1011 if (0 == memcmp(*inbuf, DADDR(d), d->size)) { 1012 TRACE_MESSAGE('E', 1013 ("escape seq: discard=%ld chars\n", 1014 d->size)); 1015 TRACE_MESSAGE('E', 1016 ("escape seq (default " 1017 "action=%6p, type=%ld) set\n", 1018 direc->action.itm_ptr, 1019 ((itm_tbl_hdr_t *) 1020 (ADDR(direc->action)))->type)); 1021 ist->default_action = direc->action; 1022 DISCARD(d->size); 1023 retval = 2; 1024 goto eval_cond_return; 1025 } 1026 } 1027 if (0 == retval) { 1028 goto eval_cond_return; 1029 } 1030 break; /* continue */ 1031 case ITM_COND_EXPR: 1032 retval = eval_expr(ist, cond->operand.place, 1033 *inbytesleft, ip, outbytesleft); 1034 if (0 == retval) { 1035 goto eval_cond_return; 1036 } else { 1037 retval = 1; 1038 } 1039 break; /* continue */ 1040 default: 1041 TRACE_MESSAGE('e', ("eval_cond_tbl:illegal cond=%d\n", 1042 cond->type)); 1043 retval = (size_t)-1; 1044 goto eval_cond_return; 1045 } 1046 } 1047 1048 eval_cond_return: 1049 return (retval); 1050 } 1051 1052 /* 1053 * Evaluate operation table 1054 * 1055 */ 1056 static size_t 1057 eval_op_tbl( 1058 icv_state_t *ist, 1059 itm_place_t op_tbl_place, 1060 const unsigned char **inbuf, 1061 size_t *inbytesleft, 1062 unsigned char **outbuf, 1063 size_t *outbytesleft) 1064 { 1065 itm_tbl_hdr_t *op_hdr; 1066 itm_op_t *operation; 1067 itm_place2_t op_place; 1068 size_t retval; 1069 long i; 1070 1071 retval = 0; 1072 1073 #if defined(OP_DEPTH_MAX) 1074 if (OP_DEPTH_MAX <= ist->op_depth) { 1075 errno = ELIBBAD; 1076 TRACE_MESSAGE('e', ("eval_op_tbl:error=%d\n", errno)); 1077 return (RETVALERR); 1078 } 1079 ist->op_depth += 1; 1080 #endif /* OP_DEPTH_MAX */ 1081 1082 op_hdr = ADDR(op_tbl_place); 1083 operation = (itm_op_t *)(op_hdr + 1); 1084 1085 op_place = op_tbl_place.itm_ptr + (sizeof (itm_tbl_hdr_t)); 1086 for (i = 0; i < op_hdr->number; i++, operation++, 1087 op_place += (sizeof (itm_op_t))) { 1088 TRACE_MESSAGE('O', ("eval_op_tbl: %ld %p\n", i, op_place)); 1089 retval = eval_op(ist, op_place, inbuf, inbytesleft, 1090 outbuf, outbytesleft); 1091 if (((long)(retval)) < 0) { 1092 #if defined(OP_DEPTH_MAX) 1093 ist->op_depth -= 1; 1094 #endif /* OP_DEPTH_MAX */ 1095 switch (retval) { 1096 case RETVALERR: 1097 return (retval); 1098 case RETVALRET: 1099 if (0 == op_hdr->name.itm_ptr) { 1100 return (RETVALRET); 1101 } else { 1102 return (0); 1103 } 1104 } 1105 } 1106 } 1107 #if defined(OP_DEPTH_MAX) 1108 ist->op_depth -= 1; 1109 #endif /* OP_DEPTH_MAX */ 1110 return (retval); 1111 } 1112 1113 1114 /* 1115 * Evaluate single operation 1116 * 1117 */ 1118 static size_t 1119 eval_op( 1120 icv_state_t *ist, 1121 itm_place2_t op_place, 1122 const unsigned char **inbuf, 1123 size_t *inbytesleft, 1124 unsigned char **outbuf, 1125 size_t *outbytesleft) 1126 { 1127 size_t retval; 1128 itm_num_t num; 1129 itm_op_t *operation; 1130 itm_expr_t *expr; 1131 itm_num_t c; 1132 itm_num_t i; 1133 itm_size_t z; 1134 unsigned char *p; 1135 itm_expr_t *expr0; 1136 itm_tbl_hdr_t *h; 1137 itm_type_t t; 1138 1139 #define EVAL_EXPR(n) \ 1140 (expr0 = ADDR(operation->data.operand[(n)]), \ 1141 (itm_num_t)((expr0->type == ITM_EXPR_INT) ? \ 1142 expr0->data.itm_exnum : \ 1143 ((expr0->type == ITM_EXPR_REG) ? \ 1144 REG(expr0->data.itm_exnum) : \ 1145 ((expr0->type == ITM_EXPR_IN_VECTOR_D) ? \ 1146 ((expr0->data.itm_exnum < 0) ? \ 1147 (((-1) == expr0->data.itm_exnum) ? *inbytesleft : 0) : \ 1148 ((expr0->data.itm_exnum < *inbytesleft) ? \ 1149 (*(uchar_t *)(*inbuf + expr0->data.itm_exnum)) : 0)): \ 1150 eval_expr(ist, operation->data.operand[(n)], \ 1151 *inbytesleft, *inbuf, *outbytesleft))))) 1152 1153 retval = 0; 1154 1155 operation = (itm_op_t *)ADDR2(op_place); 1156 1157 switch (operation->type) { 1158 case ITM_OP_EXPR: 1159 num = eval_expr(ist, operation->data.operand[0], 1160 *inbytesleft, *inbuf, *outbytesleft); 1161 TRACE_MESSAGE('o', ("ITM_OP_EXPR: %ld\n", retval)); 1162 break; 1163 case ITM_OP_ERROR: 1164 num = eval_expr(ist, operation->data.operand[0], 1165 *inbytesleft, *inbuf, *outbytesleft); 1166 errno = (int)num; 1167 TRACE_MESSAGE('o', ("ITM_OP_ERROR: %ld\n", num)); 1168 retval = (size_t)(-1); 1169 break; 1170 case ITM_OP_ERROR_D: 1171 errno = (int)operation->data.itm_opnum; 1172 TRACE_MESSAGE('o', ("ITM_OP_ERROR_D: %d\n", errno)); 1173 retval = (size_t)(-1); 1174 break; 1175 case ITM_OP_OUT: 1176 expr = ADDR(operation->data.operand[0]); 1177 if ((*outbytesleft) == 0) { 1178 errno = E2BIG; 1179 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno)); 1180 return ((size_t)(-1)); 1181 } 1182 c = eval_expr(ist, operation->data.operand[0], 1183 *inbytesleft, *inbuf, *outbytesleft); 1184 PUT((uchar_t)c); 1185 retval = *inbytesleft; 1186 TRACE_MESSAGE('o', ("ITM_OP_OUT: %ld %ld\n", c, *inbytesleft)); 1187 break; 1188 case ITM_OP_OUT_D: 1189 expr = ADDR(operation->data.operand[0]); 1190 if ((*outbytesleft) == 0) { 1191 errno = E2BIG; 1192 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno)); 1193 return ((size_t)(-1)); 1194 } 1195 PUT(0xff & (expr->data.itm_exnum)); 1196 break; 1197 case ITM_OP_OUT_S: 1198 expr = ADDR(operation->data.operand[0]); 1199 if ((*outbytesleft) == 0) { 1200 errno = E2BIG; 1201 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno)); 1202 return ((size_t)(-1)); 1203 } 1204 z = expr->data.value.size; 1205 if (*outbytesleft < z) { 1206 errno = E2BIG; 1207 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno)); 1208 return ((size_t)(-1)); 1209 } 1210 p = DADDR(&(expr->data.value)); 1211 for (; 0 < z; --z, p++) { 1212 PUT(*p); 1213 } 1214 break; 1215 case ITM_OP_OUT_R: 1216 expr = ADDR(operation->data.operand[0]); 1217 if ((*outbytesleft) == 0) { 1218 errno = E2BIG; 1219 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno)); 1220 return ((size_t)(-1)); 1221 } 1222 c = REG(expr->data.itm_exnum); 1223 PUT((uchar_t)c); 1224 break; 1225 case ITM_OP_OUT_INVD: 1226 expr = ADDR(operation->data.operand[0]); 1227 if ((*outbytesleft) == 0) { 1228 errno = E2BIG; 1229 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno)); 1230 return ((size_t)(-1)); 1231 } 1232 z = (((0 <= expr->data.itm_exnum) && 1233 (expr->data.itm_exnum < *inbytesleft)) ? 1234 (*((unsigned char *)(*inbuf + expr->data.itm_exnum))) : 1235 (((-1) == expr->data.itm_exnum) ? *inbytesleft : 0)); 1236 PUT((uchar_t)z); 1237 break; 1238 case ITM_OP_DISCARD: 1239 #if defined(EVAL_EXPR) 1240 num = EVAL_EXPR(0); 1241 #else /* !defined(EVAL_EXPR) */ 1242 num = eval_expr(ist, operation->data.operand[0], 1243 *inbytesleft, *inbuf, *outbytesleft); 1244 #endif /* defined(EVAL_EXPR) */ 1245 TRACE_MESSAGE('o', ("ITM_OP_DISCARD: %ld\n", num)); 1246 #if defined(DISCARD) 1247 DISCARD((num <= *inbytesleft) ? ((ulong_t)num) : *inbytesleft); 1248 #else /* defined(DISCARD) */ 1249 for (num = ((num <= *inbytesleft) ? num : *inbytesleft); 1250 0 < num; --num) { 1251 GET(c); 1252 } 1253 #endif /* defined(DISCARD) */ 1254 break; 1255 case ITM_OP_DISCARD_D: 1256 num = operation->data.itm_opnum; 1257 TRACE_MESSAGE('o', ("ITM_OP_DISCARD_D: %ld\n", num)); 1258 #if defined(DISCARD) 1259 DISCARD((num <= *inbytesleft) ? num : *inbytesleft); 1260 #else /* defined(DISCARD) */ 1261 for (num = ((num <= *inbytesleft) ? num : *inbytesleft); 1262 0 < num; --num) { 1263 GET(c); 1264 } 1265 #endif /* defined(DISCARD) */ 1266 break; 1267 case ITM_OP_IF: 1268 c = eval_expr(ist, operation->data.operand[0], 1269 *inbytesleft, *inbuf, *outbytesleft); 1270 TRACE_MESSAGE('o', ("ITM_OP_IF: %ld\n", c)); 1271 if (c) { 1272 retval = eval_op_tbl(ist, operation->data.operand[1], 1273 inbuf, inbytesleft, outbuf, outbytesleft); 1274 } 1275 break; 1276 case ITM_OP_IF_ELSE: 1277 c = eval_expr(ist, operation->data.operand[0], 1278 *inbytesleft, *inbuf, *outbytesleft); 1279 TRACE_MESSAGE('o', ("ITM_OP_IF_ELSE: %ld\n", c)); 1280 if (c) { 1281 retval = eval_op_tbl(ist, operation->data.operand[1], 1282 inbuf, inbytesleft, outbuf, outbytesleft); 1283 } else { 1284 retval = eval_op_tbl(ist, operation->data.operand[2], 1285 inbuf, inbytesleft, outbuf, outbytesleft); 1286 } 1287 break; 1288 case ITM_OP_DIRECTION: 1289 TRACE_MESSAGE('o', ("ITM_OP_DIRECTION: %p\n", 1290 operation->data.operand[0].itm_ptr)); 1291 ist->direc = ADDR(operation->data.operand[0]); 1292 return ((size_t)(-2)); 1293 case ITM_OP_MAP: 1294 TRACE_MESSAGE('o', ("ITM_OP_MAP: %p\n", 1295 operation->data.operand[0].itm_ptr)); 1296 i = 0; 1297 if (0 != operation->data.operand[1].itm_ptr) { 1298 #if defined(EVAL_EXPR) 1299 i = EVAL_EXPR(1); 1300 #else /* !defined(EVAL_EXPR) */ 1301 i = eval_expr(ist, operation->data.operand[1], 1302 *inbytesleft, *inbuf, *outbytesleft); 1303 #endif /* defined(EVAL_EXPR) */ 1304 (*inbytesleft) -= i; 1305 (*inbuf) += i; 1306 } 1307 1308 /* 1309 * Based on what is the maptype, we call the corresponding 1310 * mapping function. 1311 */ 1312 h = ADDR(operation->data.operand[0]); 1313 t = h->type; 1314 switch (t) { 1315 case ITM_TBL_MAP_INDEX_FIXED: 1316 case ITM_TBL_MAP_INDEX_FIXED_1_1: 1317 retval = map_i_f(h, inbuf, inbytesleft, 1318 outbuf, outbytesleft, 1); 1319 break; 1320 case ITM_TBL_MAP_HASH: 1321 retval = map_h_l(h, inbuf, inbytesleft, 1322 outbuf, outbytesleft, 1); 1323 break; 1324 case ITM_TBL_MAP_DENSE_ENC: 1325 retval = map_d_e_l(h, inbuf, inbytesleft, 1326 outbuf, outbytesleft, 1); 1327 break; 1328 case ITM_TBL_MAP_LOOKUP: 1329 retval = map_l_f(h, inbuf, inbytesleft, 1330 outbuf, outbytesleft, 1); 1331 break; 1332 default: 1333 /* 1334 * This should not be possible, but in case we 1335 * have an incorrect maptype, don't fall back to 1336 * map_i_f(). Instead, because it is an error, return 1337 * an error. See CR 6622765. 1338 */ 1339 errno = EBADF; 1340 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno)); 1341 retval = (size_t)-1; 1342 break; 1343 } 1344 1345 if ((size_t)(-1) == retval) { 1346 (*outbytesleft) += i; 1347 (*outbuf) -= i; 1348 } 1349 break; 1350 case ITM_OP_OPERATION: 1351 TRACE_MESSAGE('o', ("ITM_OP_OPERATION: %p\n", 1352 operation->data.operand[0].itm_ptr)); 1353 retval = eval_op_tbl(ist, operation->data.operand[0], 1354 inbuf, inbytesleft, outbuf, outbytesleft); 1355 1356 break; 1357 case ITM_OP_INIT: 1358 TRACE_MESSAGE('o', ("ITM_OP_INIT: %p\n", 1359 ist->itm_hdr->op_init_tbl)); 1360 if (0 != ist->itm_hdr->op_init_tbl.itm_ptr) { 1361 retval = eval_op_tbl(ist, ist->itm_hdr->op_init_tbl, 1362 inbuf, inbytesleft, outbuf, outbytesleft); 1363 } else { 1364 op_init_default(ist); 1365 retval = (size_t)-2; 1366 } 1367 break; 1368 case ITM_OP_RESET: 1369 TRACE_MESSAGE('o', ("ITM_OP_RESET: %p\n", 1370 ist->itm_hdr->op_reset_tbl)); 1371 if (0 != ist->itm_hdr->op_reset_tbl.itm_ptr) { 1372 retval = eval_op_tbl(ist, ist->itm_hdr->op_reset_tbl, 1373 inbuf, inbytesleft, outbuf, outbytesleft); 1374 } else { 1375 op_reset_default(ist); 1376 retval = (size_t)-2; 1377 } 1378 break; 1379 case ITM_OP_BREAK: 1380 TRACE_MESSAGE('o', ("ITM_OP_BREAK\n")); 1381 return (RETVALBRK); 1382 case ITM_OP_RETURN: 1383 TRACE_MESSAGE('o', ("ITM_OP_RETURN\n")); 1384 return (RETVALRET); 1385 case ITM_OP_PRINTCHR: 1386 c = eval_expr(ist, operation->data.operand[0], *inbytesleft, 1387 *inbuf, *outbytesleft); 1388 (void) fputc((uchar_t)c, stderr); 1389 TRACE_MESSAGE('o', ("ITM_OP_PRINTCHR: %ld %ld\n", 1390 c, *inbytesleft)); 1391 break; 1392 case ITM_OP_PRINTHD: 1393 c = eval_expr(ist, operation->data.operand[0], *inbytesleft, 1394 *inbuf, *outbytesleft); 1395 (void) fprintf(stderr, "%lx", c); 1396 TRACE_MESSAGE('o', ("ITM_OP_PRINTHD: %ld %ld\n", 1397 c, *inbytesleft)); 1398 break; 1399 case ITM_OP_PRINTINT: 1400 c = eval_expr(ist, operation->data.operand[0], *inbytesleft, 1401 *inbuf, *outbytesleft); 1402 (void) fprintf(stderr, "%ld", c); 1403 TRACE_MESSAGE('o', ("ITM_OP_PRINTINT: %ld %ld\n", 1404 c, *inbytesleft)); 1405 break; 1406 default: /* never */ 1407 errno = ELIBBAD; 1408 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno)); 1409 return (size_t)(-1); 1410 } 1411 return (retval); 1412 1413 #undef EVAL_EXPR 1414 } 1415 1416 1417 /* 1418 * Evaluate expression 1419 */ 1420 static itm_num_t 1421 eval_expr( 1422 icv_state_t *ist, 1423 itm_place_t expr_place, 1424 size_t inbytesleft, 1425 const unsigned char *inbuf, 1426 size_t outbytesleft) 1427 { 1428 itm_expr_t *expr; 1429 itm_expr_t *expr_op; 1430 itm_num_t num; 1431 unsigned char *p; 1432 long i; 1433 itm_expr_t *expr0; 1434 itm_num_t num00; 1435 itm_num_t num01; 1436 1437 #define EVAL_EXPR_E(n) (eval_expr(ist, expr->data.operand[(n)], \ 1438 inbytesleft, inbuf, outbytesleft)) 1439 #define EVAL_EXPR_D(n) ((itm_num_t)(expr->data.operand[(n)].itm_ptr)) 1440 #define EVAL_EXPR_R(n) (REG((itm_num_t)(expr->data.operand[(n)].itm_ptr))) 1441 #define EVAL_EXPR_INVD(n) \ 1442 ((num0 ## n) = ((itm_num_t)(expr->data.operand[(n)].itm_ptr)), \ 1443 ((num0 ## n) < 0) ? \ 1444 (((-1) == (num0 ## n)) ? inbytesleft : 0) : \ 1445 (((num0 ## n) < inbytesleft) ? \ 1446 (*(unsigned char *)(inbuf + (num0 ## n))) : 0)) 1447 #define EVAL_EXPR(n) \ 1448 (expr0 = ADDR(expr->data.operand[(n)]), \ 1449 (itm_num_t)((expr0->type == ITM_EXPR_INT) ? \ 1450 expr0->data.itm_exnum : \ 1451 ((expr0->type == ITM_EXPR_REG) ? \ 1452 REG(expr0->data.itm_exnum) : \ 1453 ((expr0->type == ITM_EXPR_IN_VECTOR_D) ? \ 1454 ((expr0->data.itm_exnum < 0) ? \ 1455 (((-1) == expr0->data.itm_exnum) ? inbytesleft : 0) : \ 1456 ((expr0->data.itm_exnum < inbytesleft) ? \ 1457 (*(uchar_t *)(inbuf + expr0->data.itm_exnum)) : 0)) : \ 1458 eval_expr(ist, expr->data.operand[(n)], \ 1459 inbytesleft, inbuf, outbytesleft))))) 1460 1461 #define EVAL_OP_BIN_PROTO(op, name, name0, name1) \ 1462 case ITM_EXPR_##name##_##name0##_##name1: \ 1463 return (EVAL_EXPR_##name0(0) op EVAL_EXPR_##name1(1)); 1464 1465 #define EVAL_OP_BIN1(op, name) \ 1466 EVAL_OP_BIN_PROTO(op, name, E, E) \ 1467 EVAL_OP_BIN_PROTO(op, name, E, D) \ 1468 EVAL_OP_BIN_PROTO(op, name, E, R) \ 1469 EVAL_OP_BIN_PROTO(op, name, E, INVD) 1470 1471 #define EVAL_OP_BIN2(op, name) \ 1472 EVAL_OP_BIN_PROTO(op, name, D, E) \ 1473 EVAL_OP_BIN_PROTO(op, name, D, D) \ 1474 EVAL_OP_BIN_PROTO(op, name, D, R) \ 1475 EVAL_OP_BIN_PROTO(op, name, D, INVD) 1476 1477 #define EVAL_OP_BIN3(op, name) \ 1478 EVAL_OP_BIN_PROTO(op, name, R, E) \ 1479 EVAL_OP_BIN_PROTO(op, name, R, D) \ 1480 EVAL_OP_BIN_PROTO(op, name, R, R) \ 1481 EVAL_OP_BIN_PROTO(op, name, R, INVD) 1482 1483 #define EVAL_OP_BIN4(op, name) \ 1484 EVAL_OP_BIN_PROTO(op, name, INVD, E) \ 1485 EVAL_OP_BIN_PROTO(op, name, INVD, D) \ 1486 EVAL_OP_BIN_PROTO(op, name, INVD, R) \ 1487 EVAL_OP_BIN_PROTO(op, name, INVD, INVD) 1488 1489 #define EVAL_OP_BIN_PROTECT_PROTO(op, name, name0, name1) \ 1490 case ITM_EXPR_##name##_##name0##_##name1: \ 1491 num = EVAL_EXPR_##name1(1); \ 1492 if (0 != num) { \ 1493 return (EVAL_EXPR_##name0(0) op num); \ 1494 } else { \ 1495 return (0); \ 1496 } 1497 1498 #define EVAL_OP_BIN_PROTECT1(op, name) \ 1499 EVAL_OP_BIN_PROTECT_PROTO(op, name, E, E) \ 1500 EVAL_OP_BIN_PROTECT_PROTO(op, name, E, D) \ 1501 EVAL_OP_BIN_PROTECT_PROTO(op, name, E, R) \ 1502 EVAL_OP_BIN_PROTECT_PROTO(op, name, E, INVD) 1503 1504 #define EVAL_OP_BIN_PROTECT2(op, name) \ 1505 EVAL_OP_BIN_PROTECT_PROTO(op, name, D, E) \ 1506 EVAL_OP_BIN_PROTECT_PROTO(op, name, D, D) \ 1507 EVAL_OP_BIN_PROTECT_PROTO(op, name, D, R) \ 1508 EVAL_OP_BIN_PROTECT_PROTO(op, name, D, INVD) 1509 1510 #define EVAL_OP_BIN_PROTECT3(op, name) \ 1511 EVAL_OP_BIN_PROTECT_PROTO(op, name, R, E) \ 1512 EVAL_OP_BIN_PROTECT_PROTO(op, name, R, D) \ 1513 EVAL_OP_BIN_PROTECT_PROTO(op, name, R, R) \ 1514 EVAL_OP_BIN_PROTECT_PROTO(op, name, R, INVD) 1515 1516 #define EVAL_OP_BIN_PROTECT4(op, name) \ 1517 EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, E) \ 1518 EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, D) \ 1519 EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, R) \ 1520 EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, INVD) 1521 1522 expr = ADDR(expr_place); 1523 1524 switch (expr->type) { 1525 case ITM_EXPR_NONE: /* not used */ 1526 return (0); 1527 case ITM_EXPR_NOP: /* not used */ 1528 return (0); 1529 case ITM_EXPR_NAME: /* not used */ 1530 return (0); 1531 case ITM_EXPR_INT: /* integer */ 1532 return (expr->data.itm_exnum); 1533 case ITM_EXPR_SEQ: /* byte sequence */ 1534 if ((sizeof (itm_place_t)) < expr->data.value.size) { 1535 p = (unsigned char *)ADDR(expr->data.value.place); 1536 } else { 1537 p = (unsigned char *)&(expr->data.value.place); 1538 } 1539 for (i = 0, num = 0; i < expr->data.value.size; i++, p++) { 1540 num = ((num << 8) | *p); 1541 } 1542 return (num); 1543 case ITM_EXPR_REG: /* register */ 1544 return (REG(expr->data.itm_exnum)); 1545 case ITM_EXPR_IN_VECTOR: /* in[expr] */ 1546 num = EVAL_EXPR(0); 1547 if ((0 <= num) && (num < inbytesleft)) { 1548 return (*((unsigned char *)(inbuf + num))); 1549 } else if ((-1) == num) { 1550 return (inbytesleft); 1551 } else { 1552 return (0); 1553 } 1554 case ITM_EXPR_IN_VECTOR_D: /* in[DECIMAL] */ 1555 num = expr->data.itm_exnum; 1556 if ((0 <= num) && (num < inbytesleft)) { 1557 return (*((unsigned char *)(inbuf + num))); 1558 } else if ((-1) == num) { 1559 return (inbytesleft); 1560 } else { 1561 return (0); 1562 } 1563 case ITM_EXPR_OUT: /* out */ 1564 return (outbytesleft); 1565 case ITM_EXPR_TRUE: /* true */ 1566 return (1); 1567 case ITM_EXPR_FALSE: /* false */ 1568 return (0); 1569 case ITM_EXPR_UMINUS: /* unary minus */ 1570 return ((-1) * EVAL_EXPR(0)); 1571 #define PLUS_FOR_CSTYLE_CLEAN + 1572 #define MINUS_FOR_CSTYLE_CLEAN - 1573 #define MUL_FOR_CSTYLE_CLEAN * 1574 #define DIV_FOR_CSTYLE_CLEAN / 1575 #define MOD_FOR_CSTYLE_CLEAN % 1576 #define SHIFT_L_FOR_CSTYLE_CLEAN << 1577 #define SHIFT_R_FOR_CSTYLE_CLEAN >> 1578 #define OR_FOR_CSTYLE_CLEAN | 1579 #define XOR_FOR_CSTYLE_CLEAN ^ 1580 #define AND_FOR_CSTYLE_CLEAN & 1581 #define EQ_FOR_CSTYLE_CLEAN == 1582 #define NE_FOR_CSTYLE_CLEAN != 1583 #define GT_FOR_CSTYLE_CLEAN > 1584 #define GE_FOR_CSTYLE_CLEAN >= 1585 #define LT_FOR_CSTYLE_CLEAN < 1586 #define LE_FOR_CSTYLE_CLEAN <= 1587 EVAL_OP_BIN1(PLUS_FOR_CSTYLE_CLEAN, PLUS) /* A + B */ 1588 EVAL_OP_BIN2(PLUS_FOR_CSTYLE_CLEAN, PLUS) /* A + B */ 1589 EVAL_OP_BIN3(PLUS_FOR_CSTYLE_CLEAN, PLUS) /* A + B */ 1590 EVAL_OP_BIN4(PLUS_FOR_CSTYLE_CLEAN, PLUS) /* A + B */ 1591 1592 EVAL_OP_BIN1(MINUS_FOR_CSTYLE_CLEAN, MINUS) /* A - B */ 1593 EVAL_OP_BIN2(MINUS_FOR_CSTYLE_CLEAN, MINUS) /* A - B */ 1594 EVAL_OP_BIN3(MINUS_FOR_CSTYLE_CLEAN, MINUS) /* A - B */ 1595 EVAL_OP_BIN4(MINUS_FOR_CSTYLE_CLEAN, MINUS) /* A - B */ 1596 1597 EVAL_OP_BIN1(MUL_FOR_CSTYLE_CLEAN, MUL) /* A * B */ 1598 EVAL_OP_BIN2(MUL_FOR_CSTYLE_CLEAN, MUL) /* A * B */ 1599 EVAL_OP_BIN3(MUL_FOR_CSTYLE_CLEAN, MUL) /* A * B */ 1600 EVAL_OP_BIN4(MUL_FOR_CSTYLE_CLEAN, MUL) /* A * B */ 1601 1602 EVAL_OP_BIN_PROTECT1(DIV_FOR_CSTYLE_CLEAN, DIV) /* A / B */ 1603 EVAL_OP_BIN_PROTECT2(DIV_FOR_CSTYLE_CLEAN, DIV) /* A / B */ 1604 EVAL_OP_BIN_PROTECT3(DIV_FOR_CSTYLE_CLEAN, DIV) /* A / B */ 1605 EVAL_OP_BIN_PROTECT4(DIV_FOR_CSTYLE_CLEAN, DIV) /* A / B */ 1606 1607 EVAL_OP_BIN_PROTECT1(MOD_FOR_CSTYLE_CLEAN, MOD) /* A % B */ 1608 EVAL_OP_BIN_PROTECT2(MOD_FOR_CSTYLE_CLEAN, MOD) /* A % B */ 1609 EVAL_OP_BIN_PROTECT3(MOD_FOR_CSTYLE_CLEAN, MOD) /* A % B */ 1610 EVAL_OP_BIN_PROTECT4(MOD_FOR_CSTYLE_CLEAN, MOD) /* A % B */ 1611 1612 EVAL_OP_BIN1(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L) /* A << B */ 1613 EVAL_OP_BIN2(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L) /* A << B */ 1614 EVAL_OP_BIN3(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L) /* A << B */ 1615 EVAL_OP_BIN4(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L) /* A << B */ 1616 1617 EVAL_OP_BIN1(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R) /* A >> B */ 1618 EVAL_OP_BIN2(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R) /* A >> B */ 1619 EVAL_OP_BIN3(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R) /* A >> B */ 1620 EVAL_OP_BIN4(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R) /* A >> B */ 1621 1622 EVAL_OP_BIN1(OR_FOR_CSTYLE_CLEAN, OR) /* A | B */ 1623 EVAL_OP_BIN2(OR_FOR_CSTYLE_CLEAN, OR) /* A | B */ 1624 EVAL_OP_BIN3(OR_FOR_CSTYLE_CLEAN, OR) /* A | B */ 1625 EVAL_OP_BIN4(OR_FOR_CSTYLE_CLEAN, OR) /* A | B */ 1626 1627 EVAL_OP_BIN1(XOR_FOR_CSTYLE_CLEAN, XOR) /* A ^ B */ 1628 EVAL_OP_BIN2(XOR_FOR_CSTYLE_CLEAN, XOR) /* A ^ B */ 1629 EVAL_OP_BIN3(XOR_FOR_CSTYLE_CLEAN, XOR) /* A ^ B */ 1630 EVAL_OP_BIN4(XOR_FOR_CSTYLE_CLEAN, XOR) /* A ^ B */ 1631 1632 EVAL_OP_BIN1(AND_FOR_CSTYLE_CLEAN, AND) /* A & B */ 1633 EVAL_OP_BIN2(AND_FOR_CSTYLE_CLEAN, AND) /* A & B */ 1634 EVAL_OP_BIN3(AND_FOR_CSTYLE_CLEAN, AND) /* A & B */ 1635 EVAL_OP_BIN4(AND_FOR_CSTYLE_CLEAN, AND) /* A & B */ 1636 1637 EVAL_OP_BIN1(EQ_FOR_CSTYLE_CLEAN, EQ) /* A == B */ 1638 EVAL_OP_BIN2(EQ_FOR_CSTYLE_CLEAN, EQ) /* A == B */ 1639 EVAL_OP_BIN3(EQ_FOR_CSTYLE_CLEAN, EQ) /* A == B */ 1640 EVAL_OP_BIN4(EQ_FOR_CSTYLE_CLEAN, EQ) /* A == B */ 1641 1642 EVAL_OP_BIN1(NE_FOR_CSTYLE_CLEAN, NE) /* A != B */ 1643 EVAL_OP_BIN2(NE_FOR_CSTYLE_CLEAN, NE) /* A != B */ 1644 EVAL_OP_BIN3(NE_FOR_CSTYLE_CLEAN, NE) /* A != B */ 1645 EVAL_OP_BIN4(NE_FOR_CSTYLE_CLEAN, NE) /* A != B */ 1646 1647 EVAL_OP_BIN1(GT_FOR_CSTYLE_CLEAN, GT) /* A > B */ 1648 EVAL_OP_BIN2(GT_FOR_CSTYLE_CLEAN, GT) /* A > B */ 1649 EVAL_OP_BIN3(GT_FOR_CSTYLE_CLEAN, GT) /* A > B */ 1650 EVAL_OP_BIN4(GT_FOR_CSTYLE_CLEAN, GT) /* A > B */ 1651 1652 EVAL_OP_BIN1(GE_FOR_CSTYLE_CLEAN, GE) /* A >= B */ 1653 EVAL_OP_BIN2(GE_FOR_CSTYLE_CLEAN, GE) /* A >= B */ 1654 EVAL_OP_BIN3(GE_FOR_CSTYLE_CLEAN, GE) /* A >= B */ 1655 EVAL_OP_BIN4(GE_FOR_CSTYLE_CLEAN, GE) /* A >= B */ 1656 1657 EVAL_OP_BIN1(LT_FOR_CSTYLE_CLEAN, LT) /* A < B */ 1658 EVAL_OP_BIN2(LT_FOR_CSTYLE_CLEAN, LT) /* A < B */ 1659 EVAL_OP_BIN3(LT_FOR_CSTYLE_CLEAN, LT) /* A < B */ 1660 EVAL_OP_BIN4(LT_FOR_CSTYLE_CLEAN, LT) /* A < B */ 1661 1662 EVAL_OP_BIN1(LE_FOR_CSTYLE_CLEAN, LE) /* A <= B */ 1663 EVAL_OP_BIN2(LE_FOR_CSTYLE_CLEAN, LE) /* A <= B */ 1664 EVAL_OP_BIN3(LE_FOR_CSTYLE_CLEAN, LE) /* A <= B */ 1665 EVAL_OP_BIN4(LE_FOR_CSTYLE_CLEAN, LE) /* A <= B */ 1666 1667 case ITM_EXPR_NOT: /* !A */ 1668 return (!(EVAL_EXPR(0))); 1669 case ITM_EXPR_NEG: /* ~A */ 1670 return (~(EVAL_EXPR(0))); 1671 case ITM_EXPR_LOR: /* A || B */ 1672 if (0 != (num = EVAL_EXPR(0))) 1673 return (num); 1674 if (0 != (num = EVAL_EXPR(1))) 1675 return (num); 1676 return (0); 1677 case ITM_EXPR_LAND: /* A && B */ 1678 if (0 == EVAL_EXPR(0)) 1679 return (0); 1680 if (0 == (num = EVAL_EXPR(1))) 1681 return (0); 1682 return (num); 1683 case ITM_EXPR_ASSIGN: /* A = B */ 1684 num = EVAL_EXPR(1); 1685 if (expr->data.operand[0].itm_ptr < ist->itm_hdr->reg_num) { 1686 return (*(ist->regs + expr->data.operand[0].itm_ptr) 1687 = num); 1688 } else { 1689 return (0); 1690 } 1691 case ITM_EXPR_IN_EQ: /* in == A */ 1692 expr_op = ADDR(expr->data.operand[0]); 1693 switch (expr_op->type) { 1694 case ITM_EXPR_SEQ: 1695 if (inbytesleft < expr_op->data.value.size) { 1696 return (0); 1697 } 1698 p = DADDR(&(expr_op->data.value)); 1699 for (i = 0; i < expr_op->data.value.size; i++, p++) { 1700 if (*p != *(inbuf + i)) { 1701 return (0); 1702 } 1703 } 1704 return (1); 1705 default: 1706 num = EVAL_EXPR(0); 1707 return (num == *((unsigned char *)inbuf)); 1708 } 1709 default: 1710 break; 1711 } 1712 1713 return (0); 1714 1715 #undef EVAL_EXPR_E 1716 #undef EVAL_EXPR_D 1717 #undef EVAL_EXPR_R 1718 #undef EVAL_EXPR_INVD 1719 #undef EVAL_EXPR 1720 } 1721 1722 1723 /* 1724 * maintain ITM reference information 1725 */ 1726 static void 1727 itm_ref_free(int fd, void *ptr0, void *ptr1, void *ptr2, size_t len) 1728 { 1729 int r; 1730 r = errno; 1731 if (0 <= fd) { 1732 (void) close(fd); 1733 } 1734 free(ptr0); 1735 free(ptr1); 1736 if (0 < len) { 1737 (void) munmap(ptr2, len); 1738 } 1739 errno = r; 1740 } 1741 1742 static itm_ref_t * 1743 itm_ref_inc(const char *itm) 1744 { 1745 itm_ref_t *ref; 1746 itm_hdr_t *hdr; 1747 struct stat st; 1748 int fd; 1749 1750 fd = open(itm, O_RDONLY, 0); 1751 if (fd == -1) { 1752 itm_ref_free(-1, NULL, NULL, NULL, 0); 1753 return (NULL); 1754 } 1755 1756 if (fstat(fd, &st) == -1) { 1757 itm_ref_free(fd, NULL, NULL, NULL, 0); 1758 return (NULL); 1759 } 1760 hdr = (void *) mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); 1761 if (MAP_FAILED == hdr) { 1762 itm_ref_free(fd, NULL, NULL, NULL, 0); 1763 return (NULL); 1764 } 1765 1766 (void) close(fd); 1767 1768 ref = malloc(sizeof (itm_ref_t)); 1769 if (NULL == ref) { 1770 itm_ref_free(-1, NULL, NULL, hdr, st.st_size); 1771 return (NULL); 1772 } 1773 ref->name = malloc(strlen(itm) + 1); 1774 if (NULL == ref->name) { 1775 itm_ref_free(-1, ref, NULL, hdr, st.st_size); 1776 return (NULL); 1777 } 1778 (void) strcpy(ref->name, itm); 1779 ref->hdr = hdr; 1780 ref->len = st.st_size; 1781 1782 if ((hdr->ident[0] != ITM_IDENT_0) || 1783 (hdr->ident[1] != ITM_IDENT_1) || 1784 (hdr->ident[2] != ITM_IDENT_2) || 1785 (hdr->ident[3] != ITM_IDENT_3) || 1786 (hdr->spec[0] != ITM_SPEC_0) || 1787 (hdr->spec[1] != ITM_SPEC_1) || 1788 (hdr->spec[2] != ITM_SPEC_2) || 1789 #if defined(_LITTLE_ENDIAN) 1790 #if defined(_LP64) 1791 ((hdr->spec[3] != ITM_SPEC_3_32_LITTLE_ENDIAN) && 1792 (hdr->spec[3] != ITM_SPEC_3_64_LITTLE_ENDIAN)) || 1793 #else 1794 (hdr->spec[3] != ITM_SPEC_3_32_LITTLE_ENDIAN) || 1795 #endif 1796 #else 1797 #if defined(_LP64) 1798 ((hdr->spec[3] != ITM_SPEC_3_32_BIG_ENDIAN) && 1799 (hdr->spec[3] != ITM_SPEC_3_64_BIG_ENDIAN)) || 1800 #else 1801 (hdr->spec[3] != ITM_SPEC_3_32_BIG_ENDIAN) || 1802 #endif 1803 #endif 1804 (hdr->version[0] != ITM_VER_0) || 1805 (hdr->version[1] != ITM_VER_1) || 1806 (hdr->version[2] != ITM_VER_2) || 1807 (hdr->version[3] != ITM_VER_3) || 1808 (((size_t)(hdr->itm_size.itm_ptr)) != st.st_size)) { 1809 itm_ref_free(-1, ref, ref->name, ref->hdr, ref->len); 1810 errno = ELIBBAD; 1811 TRACE_MESSAGE('e', ("itm_ref_inc:error=%d\n", errno)); 1812 return (NULL); 1813 } 1814 1815 return (ref); 1816 } 1817 1818 1819 static void 1820 itm_ref_dec(itm_ref_t *ref) 1821 { 1822 (void) munmap((char *)(ref->hdr), ref->len); 1823 free(ref->name); 1824 free(ref); 1825 } 1826 1827 1828 static void 1829 op_init_default(icv_state_t *ist) 1830 { 1831 ist->direc = ADDR(ist->itm_hdr->direc_init_tbl); 1832 regs_init(ist); 1833 } 1834 1835 1836 static void 1837 op_reset_default(icv_state_t *ist) 1838 { 1839 ist->direc = ADDR(ist->itm_hdr->direc_init_tbl); 1840 regs_init(ist); 1841 } 1842 1843 1844 static void 1845 regs_init(icv_state_t *ist) 1846 { 1847 if (0 < ist->itm_hdr->reg_num) { 1848 (void) memset(ist->regs, 0, 1849 (sizeof (itm_num_t)) * ist->itm_hdr->reg_num); 1850 } 1851 } 1852 1853 1854 #if defined(DEBUG) 1855 static void 1856 trace_init() 1857 { 1858 char *env_val; 1859 char *p; 1860 1861 env_val = getenv("ITM_INT_TRACE"); 1862 if (NULL == env_val) 1863 return; 1864 1865 for (p = env_val; *p; p++) { 1866 trace_option[(*p) & 0x007f] = 1; 1867 } 1868 } 1869 1870 static void 1871 trace_message(char *format, ...) 1872 { 1873 va_list ap; 1874 1875 va_start(ap, format); 1876 1877 (void) vfprintf(stderr, format, ap); 1878 1879 va_end(ap); 1880 } 1881 #endif /* DEBUG */ 1882