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 *
_icv_open(const char * itm)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
_icv_close(icv_state_t * ist)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
_icv_iconv(icv_state_t * ist,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft)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
map_i_f(itm_tbl_hdr_t * tbl_hdr,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft,long once)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
map_l_f(itm_tbl_hdr_t * tbl_hdr,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft,long once)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
map_h_l(itm_tbl_hdr_t * tbl_hdr,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft,long once)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
map_d_e_l(itm_tbl_hdr_t * tbl_hdr,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft,long once)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
eval_cond_tbl(icv_state_t * ist,itm_place_t cond_place,const unsigned char ** inbuf,size_t * inbytesleft,size_t outbytesleft,itm_direc_t * direc)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
eval_op_tbl(icv_state_t * ist,itm_place_t op_tbl_place,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft)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
eval_op(icv_state_t * ist,itm_place2_t op_place,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft)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
eval_expr(icv_state_t * ist,itm_place_t expr_place,size_t inbytesleft,const unsigned char * inbuf,size_t outbytesleft)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
itm_ref_free(int fd,void * ptr0,void * ptr1,void * ptr2,size_t len)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 *
itm_ref_inc(const char * itm)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
itm_ref_dec(itm_ref_t * ref)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
op_init_default(icv_state_t * ist)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
op_reset_default(icv_state_t * ist)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
regs_init(icv_state_t * ist)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
trace_init()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
trace_message(char * format,...)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