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, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1999 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <assert.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <inttypes.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <libintl.h>
40
41 #include "itmcomp.h"
42
43 struct itm_opt_outer *itm_op_outer = NULL;
44
45 #if defined(ENABLE_TRACE)
46 static char *itmc_obj_names[] = {
47 "ITMC_OBJ_NONE(0)",
48 "ITMC_OBJ_ITM(1)",
49 "ITMC_OBJ_STRING(2)",
50 "ITMC_OBJ_DIREC(3)",
51 "ITMC_OBJ_COND(4)",
52 "ITMC_OBJ_MAP(5)",
53 "ITMC_OBJ_OP(6)",
54 "ITMC_OBJ_EXPR(7)",
55 "ITMC_OBJ_DATA(8)",
56 "ITMC_OBJ_ACTION(9)",
57 "ITMC_OBJ_RANGE(10)",
58 "ITMC_OBJ_RAGISTER(11)",
59 "ITMC_OBJ_ESCAPESEQ(12)"
60 };
61 #endif
62
63 #define TRACE_FMT(comment) \
64 comment ## " size=%4ld(0x%4lx); 64d=0x%16" PRIx64 "; ptr=%4p(%c...)\n"
65 #define TRACE_DT(data, refer) \
66 data.size, data.size, data.place.itm_64d, \
67 data.place.itm_ptr,\
68 (((refer) == 0) ? (not_refer): \
69 (((sizeof (itm_place_t) < data.size))? \
70 *((char *)(((char *)itm_header) + data.place.itm_ptr)): \
71 (not_refer)))
72 enum {
73 NOREFER = 0,
74 REFER = 1
75 };
76 #define NAMETRACE(comment) \
77 { itmc_name_t *name;\
78 TRACE_MESSAGE('p', (#comment "\n")); \
79 for (name = name_first; name; name = name->next) {\
80 TRACE_MESSAGE('p', \
81 (TRACE_FMT(" "),\
82 TRACE_DT(name->name, NOREFER)));\
83 }\
84 }
85
86 /* static int not_refer = (~0); */
87
88
89
90 static void relocation_I(itm_hdr_t *, itm_info_hdr_t *);
91 static void relocation_II(itm_hdr_t *, itm_info_hdr_t *);
92
93 static void fix_itmc_ref_reloc(itmc_ref_t *, itm_place2_t);
94 static void analysis(itm_info_hdr_t *);
95 static void analysis2(void);
96 static void output(itm_hdr_t *, itm_info_hdr_t *);
97
98
99
100
101 /*
102 * Assemble main function
103 */
104
105 int
assemble(itm_hdr_t * itm_header)106 assemble(itm_hdr_t *itm_header)
107 {
108 int i;
109 int j;
110 itmc_ref_t *ref;
111 itm_info_hdr_t *info_header;
112 union {
113 long longval;
114 char charval[8];
115 } mach_spec;
116
117 if (0 < error_deferred) {
118 itm_error(gettext("number of deferred error: %d\n"),
119 error_deferred);
120 exit(ITMC_STATUS_BT);
121 }
122
123 itm_header->ident[0] = ITM_IDENT_0;
124 itm_header->ident[1] = ITM_IDENT_1;
125 itm_header->ident[2] = ITM_IDENT_2;
126 itm_header->ident[3] = ITM_IDENT_3;
127
128 itm_header->spec[0] = ITM_SPEC_0;
129 itm_header->spec[1] = ITM_SPEC_1;
130 itm_header->spec[2] = ITM_SPEC_2;
131 mach_spec.longval = 1;
132 switch (sizeof (long)) {
133 case 4:
134 if (0 == mach_spec.charval[0]) {
135 itm_header->spec[3] = ITM_SPEC_3_32_BIG_ENDIAN;
136 } else {
137 itm_header->spec[3] = ITM_SPEC_3_32_LITTLE_ENDIAN;
138 }
139 break;
140 case 8:
141 if (0 == mach_spec.charval[0]) {
142 itm_header->spec[3] = ITM_SPEC_3_64_BIG_ENDIAN;
143 } else {
144 itm_header->spec[3] = ITM_SPEC_3_64_LITTLE_ENDIAN;
145 }
146 break;
147 }
148
149 itm_header->version[0] = ITM_VER_0;
150 itm_header->version[1] = ITM_VER_1;
151 itm_header->version[2] = ITM_VER_2;
152 itm_header->version[3] = ITM_VER_3;
153
154 itm_header->itm_size.itm_ptr = 0;
155
156 itm_header->reg_num = reg_id;
157
158 itm_header->itm_hdr_size = (sizeof (itm_hdr_t));
159
160 info_header = malloc_vital(sizeof (itm_info_hdr_t));
161 (void) memset(info_header, 0, sizeof (itm_info_hdr_t));
162
163 relocation_I(itm_header, info_header);
164 relocation_II(itm_header, info_header);
165
166 TRACE_MESSAGE('r',
167 (" ref name referencee reloc(10)"
168 "size(10) referencer next\n"));
169 for (i = ITMC_OBJ_FIRST; i <= ITMC_OBJ_LAST; i++) {
170 TRACE_MESSAGE('r', ("%s\n", itmc_obj_names[i]));
171 for (ref = ref_first[i], j = 0; ref; ref = ref->next, j++) {
172 TRACE_MESSAGE('r',
173 (" %2d:%08p:%08p:%08p:%8p:%8ld:%08p:%08p\n",
174 j, ref,
175 ref->name, ref->referencee,
176 ref->reloc.itm_ptr, ref->size,
177 ref->referencer, ref->next));
178 }
179 }
180
181 analysis(info_header);
182 analysis2();
183 if (0 < error_deferred) {
184 itm_error(gettext("number of deferred error: %d\n"),
185 error_deferred);
186 exit(ITMC_STATUS_BT);
187 }
188
189 output(itm_header, info_header);
190 return (0);
191 }
192
193
194 /*
195 * Fix reloc of itmc_ref_t, and fix reloc of itmc_name_t
196 */
197
198 static void
relocation_I(itm_hdr_t * itm_header,itm_info_hdr_t * info_header)199 relocation_I(itm_hdr_t *itm_header, itm_info_hdr_t *info_header)
200 {
201 itmc_ref_t *ref;
202 itmc_name_t *name;
203 itm_num_t sec_num;
204 itm_num_t sec_num2;
205 itm_size_t sec_size;
206
207 /*
208 * determin section size
209 */
210
211 /* string section */
212 for (sec_num = 0, sec_size = 0, ref = ref_first[ITMC_OBJ_STRING];
213 ref; sec_num += 1, sec_size += ref->size, ref = ref->next) {}
214 sec_size = ITMROUNDUP(sec_size);
215 info_header->str_plc_tbl.size = ((sizeof (itm_data_t)) * sec_num);
216 info_header->str_plc_tbl.number = sec_num;
217 info_header->str_sec.size = sec_size;
218 info_header->str_sec.number = sec_num;
219
220 /* direction */
221 for (sec_num = 0, sec_size = 0, ref = ref_first[ITMC_OBJ_DIREC];
222 ref; sec_num += 1, sec_size += ref->size, ref = ref->next) {}
223 sec_size = ITMROUNDUP(sec_size);
224 info_header->direc_plc_tbl.size = sec_num * (sizeof (itm_place_t));
225 info_header->direc_plc_tbl.number = sec_num;
226 info_header->direc_tbl_sec.size = sec_size;
227 info_header->direc_tbl_sec.number = sec_num;
228
229 /* condition */
230 for (sec_num = 0, sec_size = 0, ref = ref_first[ITMC_OBJ_COND];
231 ref; sec_num += 1, sec_size += ref->size, ref = ref->next) {}
232 sec_size = ITMROUNDUP(sec_size);
233 info_header->cond_plc_tbl.size = sec_num * (sizeof (itm_place_t));
234 info_header->cond_plc_tbl.number = sec_num;
235 info_header->cond_tbl_sec.size = sec_size;
236 info_header->cond_tbl_sec.number = sec_num;
237
238 /* map */
239 for (sec_num = 0, sec_size = 0, ref = ref_first[ITMC_OBJ_MAP];
240 ref; sec_num += 1, sec_size += ref->size, ref = ref->next) {
241 }
242 sec_size = ITMROUNDUP(sec_size);
243 info_header->map_plc_tbl.size = sec_num * (sizeof (itm_place_t));
244 info_header->map_plc_tbl.number = sec_num;
245 info_header->map_tbl_sec.size = sec_size;
246 info_header->map_tbl_sec.number = sec_num;
247
248 /* operation */
249 for (sec_num = 0, sec_size = 0, ref = ref_first[ITMC_OBJ_OP];
250 ref; sec_num += 1, sec_size += ref->size, ref = ref->next) {
251 }
252 sec_size = ITMROUNDUP(sec_size);
253 info_header->op_plc_tbl.size = sec_num * (sizeof (itm_place_t));
254 info_header->op_plc_tbl.number = sec_num;
255 info_header->op_tbl_sec.size = sec_size;
256 info_header->op_tbl_sec.number = sec_num;
257
258 /* range section */
259 for (sec_num = 0, sec_size = 0, ref = ref_first[ITMC_OBJ_RANGE];
260 ref; sec_num += 1, sec_size += ref->size, ref = ref->next) {}
261 sec_size = ITMROUNDUP(sec_size);
262 info_header->range_plc_tbl.size = sec_num * (sizeof (itm_place_t));
263 info_header->range_plc_tbl.number = sec_num;
264 info_header->range_tbl_sec.size = sec_size;
265 info_header->range_tbl_sec.number = sec_num;
266
267 /* escapeseq section */
268 for (sec_num = 0, sec_size = 0, ref = ref_first[ITMC_OBJ_ESCAPESEQ];
269 ref; sec_num += 1, sec_size += ref->size, ref = ref->next) {}
270 sec_size = ITMROUNDUP(sec_size);
271 info_header->escapeseq_plc_tbl.size = sec_num * (sizeof (itm_place_t));
272 info_header->escapeseq_plc_tbl.number = sec_num;
273 info_header->escapeseq_tbl_sec.size = sec_size;
274 info_header->escapeseq_tbl_sec.number = sec_num;
275
276 /* data section */
277 for (sec_num = 0, sec_size = 0, ref = ref_first[ITMC_OBJ_DATA];
278 ref; sec_num += 1, sec_size += ref->size, ref = ref->next) {}
279 for (ref = ref_first[ITMC_OBJ_EXPR];
280 ref; sec_num += 1, sec_size += ref->size, ref = ref->next) {}
281 sec_size = ITMROUNDUP(sec_size);
282 info_header->data_plc_tbl.size = ((sizeof (itm_place_t)) * sec_num);
283 info_header->data_plc_tbl.number = sec_num;
284 info_header->data_sec.size = sec_size;
285 info_header->data_sec.number = sec_num;
286
287
288 /* name section */
289 sec_num2 = 0;
290 for (sec_num = 0, sec_size = 0, name = name_first;
291 name; name = name->next) {
292 if ((ITMC_OBJ_REGISTER != name->type) &&
293 (0 != name->name.size)) {
294 if ((sizeof (itm_place_t)) < name->name.size) {
295 sec_size += name->name.size;
296 sec_num2 += 1;
297 }
298 sec_num += 1;
299 }
300 }
301 info_header->name_plc_tbl.size = ((sizeof (itm_data_t)) * sec_num);
302 info_header->name_plc_tbl.number = sec_num;
303
304 for (sec_num = 0, name = name_first; name; name = name->next) {
305 if ((ITMC_OBJ_REGISTER == name->type) &&
306 (0 != name->name.size)) {
307 if ((sizeof (itm_place_t)) < name->name.size) {
308 sec_size += name->name.size;
309 sec_num2 += 1;
310 }
311 sec_num += 1;
312 }
313 }
314 sec_size = ITMROUNDUP(sec_size);
315 info_header->reg_plc_tbl.size =
316 ((sizeof (itm_data_t)) * (itm_header->reg_num));
317 info_header->reg_plc_tbl.number = itm_header->reg_num;
318
319 info_header->name_sec.size = sec_size;
320 info_header->name_sec.number = sec_num2;
321
322 /*
323 * adjust place
324 */
325 info_header->str_sec.place.itm_ptr =
326 0 +
327 (sizeof (itm_hdr_t));
328 info_header->direc_tbl_sec.place.itm_ptr =
329 info_header->str_sec.place.itm_ptr +
330 info_header->str_sec.size;
331 info_header->cond_tbl_sec.place.itm_ptr =
332 info_header->direc_tbl_sec.place.itm_ptr +
333 info_header->direc_tbl_sec.size;
334 info_header->map_tbl_sec.place.itm_ptr =
335 info_header->cond_tbl_sec.place.itm_ptr +
336 info_header->cond_tbl_sec.size;
337 info_header->op_tbl_sec.place.itm_ptr =
338 info_header->map_tbl_sec.place.itm_ptr +
339 info_header->map_tbl_sec.size;
340
341 info_header->range_tbl_sec.place.itm_ptr =
342 info_header->op_tbl_sec.place.itm_ptr +
343 info_header->op_tbl_sec.size;
344
345 info_header->escapeseq_tbl_sec.place.itm_ptr =
346 info_header->range_tbl_sec.place.itm_ptr +
347 info_header->range_tbl_sec.size;
348
349 info_header->data_sec.place.itm_ptr =
350 info_header->escapeseq_tbl_sec.place.itm_ptr +
351 info_header->escapeseq_tbl_sec.size;
352
353 /*
354 * adjust place: optional
355 */
356
357 if (0 == cmd_opt.strip) {
358 itm_header->info_hdr.itm_ptr =
359 info_header->data_sec.place.itm_ptr +
360 info_header->data_sec.size;
361
362 info_header->direc_plc_tbl.place.itm_ptr =
363 itm_header->info_hdr.itm_ptr +
364 (sizeof (itm_info_hdr_t));
365 info_header->cond_plc_tbl.place.itm_ptr =
366 info_header->direc_plc_tbl.place.itm_ptr +
367 info_header->direc_plc_tbl.size;
368 info_header->map_plc_tbl.place.itm_ptr =
369 info_header->cond_plc_tbl.place.itm_ptr +
370 info_header->cond_plc_tbl.size;
371 info_header->op_plc_tbl.place.itm_ptr =
372 info_header->map_plc_tbl.place.itm_ptr +
373 info_header->map_plc_tbl.size;
374
375 info_header->str_plc_tbl.place.itm_ptr =
376 info_header->op_plc_tbl.place.itm_ptr +
377 info_header->op_plc_tbl.size;
378 info_header->range_plc_tbl.place.itm_ptr =
379 info_header->str_plc_tbl.place.itm_ptr +
380 info_header->str_plc_tbl.size;
381 info_header->escapeseq_plc_tbl.place.itm_ptr =
382 info_header->range_plc_tbl.place.itm_ptr +
383 info_header->range_plc_tbl.size;
384 info_header->data_plc_tbl.place.itm_ptr =
385 info_header->escapeseq_plc_tbl.place.itm_ptr +
386 info_header->escapeseq_plc_tbl.size;
387 info_header->name_plc_tbl.place.itm_ptr =
388 info_header->data_plc_tbl.place.itm_ptr +
389 info_header->data_plc_tbl.size;
390 info_header->reg_plc_tbl.place.itm_ptr =
391 info_header->name_plc_tbl.place.itm_ptr +
392 info_header->name_plc_tbl.size;
393
394 /* name SECTION */
395 info_header->name_sec.place.itm_ptr =
396 info_header->reg_plc_tbl.place.itm_ptr +
397 info_header->reg_plc_tbl.size;
398 }
399
400 /*
401 * size of ITM
402 */
403
404 if (0 == cmd_opt.strip) {
405 itm_header->itm_size.itm_ptr =
406 info_header->name_sec.place.itm_ptr +
407 info_header->name_sec.size;
408 } else {
409 itm_header->itm_size.itm_ptr =
410 info_header->data_sec.place.itm_ptr +
411 info_header->data_sec.size;
412 }
413
414
415 /*
416 * trace
417 */
418
419 #if defined(ENABLE_TRACE)
420 dump_itm_header(itm_header, info_header);
421 #endif
422 }
423
424
425 /*
426 * Fix referencer of itmc_ref_t
427 */
428
429 static void
relocation_II(itm_hdr_t * itm_header,itm_info_hdr_t * info_header)430 relocation_II(itm_hdr_t *itm_header, itm_info_hdr_t *info_header)
431 {
432 itmc_ref_t *ref;
433 itmc_name_t *name;
434 itmc_ref_link_t *rl;
435 itm_place2_t place;
436 itm_place2_t n_plc;
437
438 /*
439 * reloc
440 */
441
442 /* string section */
443 TRACE_MESSAGE('3', ("string section\n"));
444 place = info_header->str_sec.place.itm_ptr;
445 for (ref = ref_first[ITMC_OBJ_STRING];
446 ref; place += ref->size, ref = ref->next) {
447 fix_itmc_ref_reloc(ref, place);
448 }
449
450 /* direction */
451 TRACE_MESSAGE('3', ("direction\n"));
452 place = info_header->direc_tbl_sec.place.itm_ptr;
453 for (ref = ref_first[ITMC_OBJ_DIREC];
454 ref; place += ref->size, ref = ref->next) {
455 fix_itmc_ref_reloc(ref, place);
456 }
457
458 /* condition */
459 TRACE_MESSAGE('3', ("condition\n"));
460 place = info_header->cond_tbl_sec.place.itm_ptr;
461 for (ref = ref_first[ITMC_OBJ_COND];
462 ref; place += ref->size, ref = ref->next) {
463 fix_itmc_ref_reloc(ref, place);
464 }
465
466 /* map */
467 TRACE_MESSAGE('3', ("map\n"));
468 place = info_header->map_tbl_sec.place.itm_ptr;
469 for (ref = ref_first[ITMC_OBJ_MAP];
470 ref; place += ref->size, ref = ref->next) {
471 fix_itmc_ref_reloc(ref, place);
472 }
473
474 /* operation */
475 TRACE_MESSAGE('3', ("operation\n"));
476 place = info_header->op_tbl_sec.place.itm_ptr;
477 for (ref = ref_first[ITMC_OBJ_OP];
478 ref; place += ref->size, ref = ref->next) {
479 fix_itmc_ref_reloc(ref, place);
480 }
481
482 /* range */
483 place = info_header->range_tbl_sec.place.itm_ptr;
484 for (ref = ref_first[ITMC_OBJ_RANGE];
485 ref; place += ref->size, ref = ref->next) {
486 fix_itmc_ref_reloc(ref, place);
487 }
488
489 /* escape sequence */
490 place = info_header->escapeseq_tbl_sec.place.itm_ptr;
491 for (ref = ref_first[ITMC_OBJ_ESCAPESEQ];
492 ref; place += ref->size, ref = ref->next) {
493 fix_itmc_ref_reloc(ref, place);
494 }
495 /* data section */
496 TRACE_MESSAGE('3', ("data section\n"));
497 place = info_header->data_sec.place.itm_ptr;
498 for (ref = ref_first[ITMC_OBJ_DATA];
499 ref; place += ref->size, ref = ref->next) {
500 fix_itmc_ref_reloc(ref, place);
501 }
502 for (ref = ref_first[ITMC_OBJ_EXPR];
503 ref; place += ref->size, ref = ref->next) {
504 fix_itmc_ref_reloc(ref, place);
505 }
506
507 /* name section */
508 TRACE_MESSAGE('3', ("name section\n"));
509 place = info_header->name_plc_tbl.place.itm_ptr;
510 n_plc = info_header->name_sec.place.itm_ptr;
511 for (name = name_first; name; name = name->next) {
512 if ((NULL == name->object) ||
513 (ITMC_OBJ_REGISTER == name->type) ||
514 (0 == name->name.size)) {
515 continue;
516 }
517 if ((sizeof (itm_place_t)) < name->name.size) {
518 name->reloc.itm_ptr = n_plc;
519 n_plc += name->name.size;
520 }
521 if (name->object->referencee) {
522 ((itm_tbl_hdr_t *)(name->object->referencee))->
523 name.itm_ptr = place;
524 }
525 place += (intptr_t)(sizeof (itm_data_t));
526 }
527 place = info_header->reg_plc_tbl.place.itm_ptr;
528 for (name = name_first; name; name = name->next) {
529 if ((ITMC_OBJ_REGISTER != name->type) ||
530 (0 == name->name.size)) {
531 continue;
532 }
533 if ((sizeof (itm_place_t)) < name->name.size) {
534 #if !defined(_LP64)
535 name->reloc.itm_pad = 0;
536 #endif
537 name->reloc.itm_ptr = n_plc;
538 n_plc += name->name.size;
539 }
540 place += (sizeof (itm_data_t));
541 }
542 for (name = name_first; name; name = name->next) {
543 if (ITMC_OBJ_REGISTER == name->type) {
544 assert(NULL == name->object);
545 continue;
546 }
547 if (NULL == name->object) {
548 itm_error(
549 gettext(
550 "reference to %1$s \"%2$s\" is not resolved\n"),
551 itm_name_type_name[name->type],
552 name_to_str(&(name->name)));
553 error_deferred += 1;
554 continue;
555 } /* else */
556 assert(0 != name->name.size);
557 for (rl = name->ref_first; rl; rl = rl->next) {
558 fix_itmc_ref_reloc(rl->ref,
559 name->object->reloc.itm_ptr);
560 }
561 if (NULL == name->object->referencee) {
562 itm_error(
563 gettext(
564 "reference to %1$s \"%2$s\" is not resolved\n"),
565 itm_name_type_name[name->type],
566 name_to_str(&(name->name)));
567 error_deferred += 1;
568 }
569 if (((ITMC_OBJ_REGISTER != name->type) &&
570 (ITMC_OBJ_DIREC != name->type) &&
571 ((ITMC_OBJ_MAP != name->type) ||
572 (NULL != ref_first[ITMC_OBJ_DIREC]))) &&
573 (NULL == name->ref_first)) {
574 itm_error(
575 gettext(
576 "%1$s \"%2$s\" is defined, but not referred\n"),
577 itm_name_type_name[name->type],
578 name_to_str(&(name->name)));
579 error_deferred += 1;
580 }
581 }
582
583
584 /*
585 * initial direction table
586 */
587 TRACE_MESSAGE('3', ("initial direction table\n"));
588 if (NULL != ref_first[ITMC_OBJ_DIREC]) {
589 itm_header->direc_init_tbl = ref_first[ITMC_OBJ_DIREC]->reloc;
590 } else if (NULL != ref_first[ITMC_OBJ_MAP]) {
591 itm_header->direc_init_tbl = ref_first[ITMC_OBJ_MAP]->reloc;
592 } else {
593 itm_error(gettext("No direction nor map\n"));
594 exit(ITMC_STATUS_BT);
595 }
596
597 /*
598 * init operation and reset operation
599 */
600 for (ref = ref_first[ITMC_OBJ_OP];
601 ref; place += ref->size, ref = ref->next) {
602 switch (((itm_tbl_hdr_t *)(ref->referencee))->type) {
603 case ITM_TBL_OP_INIT:
604 itm_header->op_init_tbl = ref->reloc;
605 break;
606 case ITM_TBL_OP_RESET:
607 itm_header->op_reset_tbl = ref->reloc;
608 break;
609 default:
610 break;
611 }
612 }
613 }
614
615
616 /*
617 * Fix reloc and referencer
618 */
619 static void
fix_itmc_ref_reloc(itmc_ref_t * ref,itm_place2_t place)620 fix_itmc_ref_reloc(itmc_ref_t *ref, itm_place2_t place)
621 {
622 itmc_ref_link_t *rl;
623
624 ref->reloc.itm_ptr = place;
625 #if !defined(_LP64)
626 ref->reloc.itm_pad = 0;
627 #endif
628
629 if (NULL != ref->referencer) {
630 ref->referencer->itm_ptr = place;
631 }
632
633 TRACE_MESSAGE('f', ("fix_itmc_ref_reloc: 0x%08p 0x%08p %p\n",
634 ref, ref->referencer, place));
635 TRACE_MESSAGE('F', ("fix_itmc_ref_reloc: \"%s\"\n",
636 name_to_str(ref->name ? &(ref->name->name) : NULL)));
637
638 if (NULL != ref->name) {
639 for (rl = ref->name->ref_first; rl; rl = rl->next) {
640 if ((NULL != rl->ref) &&
641 (NULL != rl->ref->referencer)) {
642 rl->ref->referencer->itm_ptr = place;
643 TRACE_MESSAGE('f',
644 ("fix_itmc_ref_reloc: "
645 "0x%08p 0x%08p\n",
646 rl->ref, rl->ref->referencer));
647 TRACE_MESSAGE('F',
648 ("fix_itmc_ref_reloc: \"%s\"\n",
649 name_to_str(ref->name ?
650 &(ref->name->name) :
651 NULL)));
652 }
653 }
654 }
655 }
656
657 /*
658 * Analysis
659 */
660 static void
analysis(itm_info_hdr_t * info_header)661 analysis(itm_info_hdr_t *info_header)
662 {
663 itmc_ref_t *ref;
664 itm_place2_t place;
665 itm_type_t obj_type;
666 enum { ONEMAP, ZEROMAP} onemap = ZEROMAP;
667
668 TRACE_MESSAGE('4', ("Analysis\n"));
669
670 place = info_header->str_sec.place.itm_ptr;
671 for (obj_type = ITMC_OBJ_FIRST; obj_type <= ITMC_OBJ_LAST; obj_type++) {
672 if (ITMC_OBJ_DIREC == obj_type) {
673 continue;
674 }
675
676 for (ref = ref_first[obj_type];
677 ref; place += ref->size, ref = ref->next) {
678 if ((NULL == ref->name) &&
679 (NULL == ref->referencer)) {
680 itm_tbl_hdr_t *tbl_hdr;
681 char *tbl_type;
682 tbl_hdr = (itm_tbl_hdr_t *)(ref->referencee);
683 if ((ITM_TBL_OP_RESET == tbl_hdr->type) ||
684 (ITM_TBL_OP_INIT == tbl_hdr->type)) {
685 continue;
686 } else if ((ITM_TBL_MAP ==
687 (ITM_TBL_MASK & tbl_hdr->type)) &&
688 (NULL == ref_first[ITMC_OBJ_DIREC])) {
689 if (ZEROMAP == onemap) {
690 onemap = ONEMAP;
691 continue;
692 } else {
693 itm_error(
694 gettext("multiple unamed map's "
695 "defined\n"));
696 error_deferred += 1;
697 continue;
698 }
699 }
700 switch (ITM_TBL_MASK & tbl_hdr->type) {
701 case ITM_TBL_ITM:
702 tbl_type =
703 itm_name_type_name[ITMC_OBJ_ITM];
704 break;
705 case ITM_TBL_DIREC:
706 tbl_type =
707 itm_name_type_name[ITMC_OBJ_DIREC];
708 break;
709 case ITM_TBL_COND:
710 tbl_type =
711 itm_name_type_name[ITMC_OBJ_COND];
712 break;
713 case ITM_TBL_OP:
714 tbl_type =
715 itm_name_type_name[ITMC_OBJ_OP];
716 break;
717 case ITM_TBL_MAP:
718 tbl_type =
719 itm_name_type_name[ITMC_OBJ_MAP];
720 break;
721 case ITM_TBL_RANGE:
722 tbl_type =
723 itm_name_type_name[ITMC_OBJ_RANGE];
724 break;
725 case ITM_TBL_ESCAPESEQ:
726 tbl_type =
727 itm_name_type_name[ITMC_OBJ_ESCAPESEQ];
728 break;
729 default:
730 tbl_type =
731 itm_name_type_name[ITMC_OBJ_NONE];
732 break;
733 }
734 itm_error(
735 gettext("unnamed %1$s-type object is "
736 "defined, but not referenced\n"),
737 tbl_type);
738 error_deferred += 1;
739 }
740 }
741 }
742 }
743
744 /*
745 * Analysis2 (check #nest of operation)
746 */
747 #define NIL -1
748 static void
analysis2(void)749 analysis2(void)
750 {
751 int i, j, k, n_op;
752 itmc_ref_t *ref;
753 itm_op_outer_t *o, *o_prev;
754 itm_op_inner_t *in, *in_prev;
755 int indegree_zero;
756 struct op_nest_vertex {
757 itmc_ref_t *ref; /* corresponding object's ref */
758 int indegree; /* indegree */
759 struct op_nest_edge *e; /* link of edge list */
760 int z_link; /* index of indegree zero */
761 int n_nest;
762 };
763 struct op_nest_edge {
764 struct op_nest_edge *e; /* link of edge list */
765 int index; /* index of edge */
766 };
767 struct op_nest_vertex *vertexes;
768 struct op_nest_edge *e, *e_prev;
769
770 TRACE_MESSAGE('5', ("Analysis2\n"));
771
772 #ifdef ENABLE_TRACE
773 for (o = itm_op_outer; o != NULL; o = o->link) {
774 TRACE_MESSAGE('L', ("op(table)%x\n", o->optbl));
775 }
776 #endif
777 i = 0;
778 for (o = itm_op_outer; o != NULL; o = o->link) {
779 for (ref = ref_first[ITMC_OBJ_OP]; ref != NULL;
780 ref = ref->next) {
781 if (o->optbl == ref->referencee) {
782 if (ref->name != NULL) {
783 o->ref = ref->name->object;
784 } else {
785 o->ref = ref;
786 }
787 TRACE_MESSAGE('l', ("op(table)%x<-ref(%x)\n",
788 o->optbl, o->ref));
789 o->ref->vertex_index = i;
790 i++;
791 break;
792 }
793 }
794 }
795
796 n_op = i;
797 if (n_op == 0)
798 return;
799 vertexes = (struct op_nest_vertex *)(malloc_vital(
800 sizeof (struct op_nest_vertex) * n_op));
801
802 for (o = itm_op_outer; o != NULL; o = o->link) {
803 if (o->ref == NULL) {
804 continue;
805 }
806 vertexes[o->ref->vertex_index].ref = o->ref;
807 vertexes[o->ref->vertex_index].e = NULL;
808 }
809
810 for (o = itm_op_outer; o != NULL; o_prev = o,
811 o = o->link, free(o_prev)) {
812 if (o->ref == NULL) {
813 continue;
814 }
815 TRACE_MESSAGE('l', ("vertexes[%d].ref=%x (optbl=%x(%s))\n",
816 o->ref->vertex_index, o->ref, o->ref->referencee,
817 name_to_str(o->ref->name == NULL ? NULL :
818 &(o->ref->name->name))));
819 for (in = o->in; in != NULL;
820 in_prev = in, in = in->in, free(in_prev)) {
821 /* make edge */
822 i = o->ref->vertex_index;
823 j = in->ref->name->object->vertex_index;
824 e = malloc_vital(sizeof (struct op_nest_edge));
825 e->index = j;
826 e->e = vertexes[i].e;
827 vertexes[i].e = e;
828 vertexes[j].indegree++;
829 TRACE_MESSAGE('l',
830 (" edge: vertexes[%d]:(%s) ->vertex[%d]:(%s)\n",
831 i,
832 name_to_str(
833 (vertexes[i].ref->name == NULL) ? NULL :
834 &(vertexes[i].ref->name->name)),
835 j,
836 name_to_str(
837 (vertexes[j].ref->name == NULL) ? NULL :
838 &(vertexes[j].ref->name->name))));
839 }
840 }
841
842 indegree_zero = NIL;
843 for (i = 0; i < n_op; i++) {
844 if (vertexes[i].indegree == 0) {
845 vertexes[i].z_link = indegree_zero;
846 indegree_zero = i;
847 }
848 }
849
850 for (i = 0; i < n_op; i++) {
851 if (indegree_zero == NIL) {
852 itm_error(
853 gettext("operation loop detected\n"));
854 exit(ITMC_STATUS_BT2);
855 }
856 k = indegree_zero;
857 indegree_zero = vertexes[indegree_zero].z_link;
858
859 if (vertexes[k].n_nest > MAXOPNEST) {
860 itm_error(
861 gettext("operation nested more than %d\n"),
862 MAXOPNEST);
863 exit(ITMC_STATUS_BT2);
864 }
865 TRACE_MESSAGE('l',
866 ("take out first vertex: vertexes[%d] (i.e.%s) "
867 "#depth=%d\n", k, name_to_str(
868 (vertexes[k].ref->name == NULL) ? NULL :
869 &(vertexes[k].ref->name->name)),
870 vertexes[k].n_nest));
871
872 for (e = vertexes[k].e; e != NULL;
873 e_prev = e, e = e->e, free(e_prev)) {
874 j = e->index;
875 if (vertexes[j].n_nest < vertexes[k].n_nest + 1) {
876 vertexes[j].n_nest =
877 vertexes[k].n_nest + 1;
878 }
879 TRACE_MESSAGE('l', (" +->vertexes[%d]:(%s) "
880 "(#indegree=%d,#depth = %d)\n",
881 j, name_to_str(&(vertexes[j].ref->name->name)),
882 vertexes[j].indegree, vertexes[j].n_nest));
883 vertexes[j].indegree--;
884 if (vertexes[j].indegree == 0) {
885 vertexes[j].z_link = indegree_zero;
886 indegree_zero = j;
887 }
888 }
889 }
890 free(vertexes);
891 }
892 #undef NIL
893
894 /*
895 * Output ITM compiled data
896 */
897 void
output(itm_hdr_t * itm_header,itm_info_hdr_t * info_header)898 output(itm_hdr_t *itm_header, itm_info_hdr_t *info_header)
899 {
900 itmc_ref_t *ref;
901 itmc_name_t *name;
902 itm_size_t sec_size;
903 struct stat st_buf;
904 int fd;
905 FILE *fp;
906
907 if (cmd_opt.no_output) {
908 return;
909 } else if (NULL == itm_output_file) {
910 fd = 1;
911 TRACE_MESSAGE('o', ("file=(stdout)\n"));
912 } else {
913 TRACE_MESSAGE('o', ("file=%s\n", itm_output_file));
914 switch (stat(itm_output_file, &st_buf)) {
915 case 0:
916 if (0 == cmd_opt.force_overwrite) {
917 itm_error(
918 gettext("target file exists\n"));
919 exit(ITMC_STATUS_CMD2);
920 }
921 break;
922 case -1:
923 if (ENOENT != errno) {
924 PERROR(gettext("stat"));
925 exit(ITMC_STATUS_CMD2);
926 }
927 break;
928 default:
929 PERROR(gettext("stat"));
930 exit(ITMC_STATUS_SYS);
931 break;
932 }
933
934 fd = open(itm_output_file, O_CREAT|O_WRONLY|O_TRUNC, 0666);
935 if (fd == -1) {
936 PERROR(gettext("open"));
937 exit(ITMC_STATUS_SYS);
938 }
939 }
940 fp = fdopen(fd, "w");
941 if (NULL == fp) {
942 PERROR(gettext("fdopen"));
943 exit(ITMC_STATUS_SYS);
944 }
945
946 if (1 == cmd_opt.strip) {
947 itm_header->info_hdr.itm_ptr = 0;
948 }
949
950 /* ITM header */
951 (void) fseek(fp, 0, SEEK_SET);
952 (void) fwrite(itm_header, sizeof (itm_hdr_t), 1, fp);
953
954 /* string section */
955 (void) fseek(fp, info_header->str_sec.place.itm_ptr, SEEK_SET);
956 TRACE_MESSAGE('P', ("str_sec.place.place=%p:\n",
957 info_header->str_sec.place.itm_ptr));
958 for (ref = ref_first[ITMC_OBJ_STRING]; ref; ref = ref->next) {
959 (void) fwrite((void *)(ref->referencee), 1, ref->size, fp);
960 }
961
962 /* direction */
963 (void) fseek(fp, info_header->direc_tbl_sec.place.itm_ptr, SEEK_SET);
964 TRACE_MESSAGE('P', ("direc_tbl_sec.place=%p:\n",
965 info_header->direc_tbl_sec.place.itm_ptr));
966 for (ref = ref_first[ITMC_OBJ_DIREC]; ref; ref = ref->next) {
967 (void) fwrite((void *)(ref->referencee), ref->size, 1, fp);
968 }
969
970 /* condition */
971 (void) fseek(fp, info_header->cond_tbl_sec.place.itm_ptr, SEEK_SET);
972 TRACE_MESSAGE('P', ("cond_tbl_sec.place=%p:\n",
973 info_header->cond_tbl_sec.place.itm_ptr));
974 for (ref = ref_first[ITMC_OBJ_COND]; ref; ref = ref->next) {
975 (void) fwrite((void *)(ref->referencee), ref->size, 1, fp);
976 }
977
978 /* map */
979 (void) fseek(fp, info_header->map_tbl_sec.place.itm_ptr, SEEK_SET);
980 TRACE_MESSAGE('P', ("map_tbl_sec.place=%p:\n",
981 info_header->map_tbl_sec.place.itm_ptr));
982 for (ref = ref_first[ITMC_OBJ_MAP]; ref; ref = ref->next) {
983 (void) fwrite((void *)(ref->referencee), ref->size, 1, fp);
984 }
985
986 /* operation */
987 (void) fseek(fp, info_header->op_tbl_sec.place.itm_ptr, SEEK_SET);
988 TRACE_MESSAGE('P', ("op_tbl_sec.place=%p:\n",
989 info_header->op_tbl_sec.place.itm_ptr));
990 for (ref = ref_first[ITMC_OBJ_OP]; ref; ref = ref->next) {
991 (void) fwrite((void *)(ref->referencee), ref->size, 1, fp);
992 }
993
994 /* range */
995 (void) fseek(fp, info_header->range_tbl_sec.place.itm_ptr, SEEK_SET);
996 TRACE_MESSAGE('P', ("range_tbl_sec.place=%p:\n",
997 info_header->range_tbl_sec.place.itm_ptr));
998 for (ref = ref_first[ITMC_OBJ_RANGE]; ref; ref = ref->next) {
999 (void) fwrite((void *)(ref->referencee), ref->size, 1, fp);
1000 }
1001
1002 /* escape sequence */
1003 (void) fseek(fp, info_header->escapeseq_tbl_sec.place.itm_ptr,
1004 SEEK_SET);
1005 TRACE_MESSAGE('P', ("escapeseq_tbl_sec.place=%p:\n",
1006 info_header->escapeseq_tbl_sec.place.itm_ptr));
1007 for (ref = ref_first[ITMC_OBJ_ESCAPESEQ]; ref; ref = ref->next) {
1008 (void) fwrite((void *)(ref->referencee), ref->size, 1, fp);
1009 }
1010
1011 /* data section */
1012 sec_size = 0;
1013 (void) fseek(fp, info_header->data_sec.place.itm_ptr, SEEK_SET);
1014 TRACE_MESSAGE('P', ("data_sec.place=%p:\n",
1015 info_header->data_sec.place.itm_ptr));
1016 for (ref = ref_first[ITMC_OBJ_DATA]; ref; ref = ref->next) {
1017 (void) fwrite((void *)(ref->referencee), ref->size, 1, fp);
1018 sec_size += ref->size;
1019 }
1020 for (ref = ref_first[ITMC_OBJ_EXPR]; ref; ref = ref->next) {
1021 (void) fwrite((void *)(ref->referencee), ref->size, 1, fp);
1022 sec_size += ref->size;
1023 }
1024 if (0 != cmd_opt.strip) {
1025 if (sec_size < info_header->data_sec.size) {
1026 (void) fwrite("\0\0\0\0", 1,
1027 info_header->data_sec.size - sec_size, fp);
1028 }
1029 } else {
1030
1031 /* ITM Info header */
1032 (void) fseek(fp, itm_header->info_hdr.itm_ptr, SEEK_SET);
1033 TRACE_MESSAGE('P', ("info_hdr=%p:\n",
1034 itm_header->info_hdr.itm_ptr));
1035 (void) fwrite(info_header, sizeof (itm_info_hdr_t), 1, fp);
1036
1037 (void) fseek(fp, info_header->direc_plc_tbl.place.itm_ptr,
1038 SEEK_SET);
1039 TRACE_MESSAGE('P', ("direc_plc_tbl.place=%p:\n",
1040 info_header->direc_plc_tbl.place.itm_ptr));
1041 for (ref = ref_first[ITMC_OBJ_DIREC]; ref; ref = ref->next) {
1042 (void) fwrite(&(ref->reloc),
1043 sizeof (itm_place_t), 1, fp);
1044 }
1045
1046 (void) fseek(fp, info_header->cond_plc_tbl.place.itm_ptr,
1047 SEEK_SET);
1048 TRACE_MESSAGE('P', ("cond_plc_tbl.place=%p:\n",
1049 info_header->cond_plc_tbl.place.itm_ptr));
1050
1051 for (ref = ref_first[ITMC_OBJ_COND]; ref; ref = ref->next) {
1052 (void) fwrite(&(ref->reloc),
1053 sizeof (itm_place_t), 1, fp);
1054 }
1055
1056 (void) fseek(fp, info_header->map_plc_tbl.place.itm_ptr,
1057 SEEK_SET);
1058 TRACE_MESSAGE('P', ("map_plc_tbl.place=%p:\n",
1059 info_header->map_plc_tbl.place.itm_ptr));
1060
1061 for (ref = ref_first[ITMC_OBJ_MAP]; ref; ref = ref->next) {
1062 (void) fwrite(&(ref->reloc),
1063 sizeof (itm_place_t), 1, fp);
1064 }
1065
1066 (void) fseek(fp, info_header->op_plc_tbl.place.itm_ptr,
1067 SEEK_SET);
1068 TRACE_MESSAGE('P', ("op_plc_tbl.place=%p:\n",
1069 info_header->op_plc_tbl.place.itm_ptr));
1070 for (ref = ref_first[ITMC_OBJ_OP]; ref; ref = ref->next) {
1071 (void) fwrite(&(ref->reloc),
1072 sizeof (itm_place_t), 1, fp);
1073 }
1074
1075 (void) fseek(fp, info_header->str_plc_tbl.place.itm_ptr,
1076 SEEK_SET);
1077 TRACE_MESSAGE('P', ("str_plc_tbl.place=%p:\n",
1078 info_header->str_plc_tbl.place.itm_ptr));
1079
1080 for (ref = ref_first[ITMC_OBJ_STRING]; ref; ref = ref->next) {
1081 itm_data_t data;
1082 #if !defined(_LP64)
1083 data.place.itm_pad = 0;
1084 data.pad = 0;
1085 #endif
1086 data.place = ref->reloc;
1087 data.size = ref->size;
1088 (void) fwrite(&data, sizeof (itm_data_t), 1, fp);
1089 }
1090
1091 (void) fseek(fp, info_header->range_plc_tbl.place.itm_ptr,
1092 SEEK_SET);
1093 TRACE_MESSAGE('P', ("range_plc_tbl.place=%p:\n",
1094 info_header->range_plc_tbl.place.itm_ptr));
1095 for (ref = ref_first[ITMC_OBJ_RANGE]; ref; ref = ref->next) {
1096 (void) fwrite(&(ref->reloc),
1097 sizeof (itm_place_t), 1, fp);
1098 }
1099 (void) fseek(fp, info_header->escapeseq_plc_tbl.place.itm_ptr,
1100 SEEK_SET);
1101 TRACE_MESSAGE('P', ("escapeseq_plc_tbl.place=%p:\n",
1102 info_header->escapeseq_plc_tbl.place.itm_ptr));
1103 for (ref = ref_first[ITMC_OBJ_ESCAPESEQ];
1104 ref; ref = ref->next) {
1105 (void) fwrite(&(ref->reloc),
1106 sizeof (itm_place_t), 1, fp);
1107 }
1108
1109 (void) fseek(fp, info_header->data_plc_tbl.place.itm_ptr,
1110 SEEK_SET);
1111 TRACE_MESSAGE('P', ("data_plc_tbl.place=%p:\n",
1112 info_header->data_plc_tbl.place.itm_ptr));
1113 for (ref = ref_first[ITMC_OBJ_DATA]; ref; ref = ref->next) {
1114 (void) fwrite(&(ref->reloc),
1115 sizeof (itm_place_t), 1, fp);
1116 }
1117 for (ref = ref_first[ITMC_OBJ_EXPR]; ref; ref = ref->next) {
1118 (void) fwrite(&(ref->reloc),
1119 sizeof (itm_place_t), 1, fp);
1120 }
1121
1122 (void) fseek(fp, info_header->name_plc_tbl.place.itm_ptr,
1123 SEEK_SET);
1124 TRACE_MESSAGE('P', ("name_plc_tbl.place=%p:\n",
1125 info_header->name_plc_tbl.place.itm_ptr));
1126 for (name = name_first, sec_size = 0;
1127 name; name = name->next) {
1128 itm_data_t data;
1129 if ((ITMC_OBJ_REGISTER == name->type) ||
1130 (0 == name->name.size)) {
1131 continue;
1132 }
1133 data.size = name->name.size;
1134 #if !defined(_LP64)
1135 data.pad = 0;
1136 #endif
1137 if ((sizeof (itm_place_t)) < data.size) {
1138 #if !defined(_LP64)
1139 data.place.itm_pad = 0;
1140 #endif
1141 data.place.itm_ptr = name->reloc.itm_ptr;
1142 } else {
1143 data.place = name->name.place;
1144 }
1145 (void) fwrite(&data, sizeof (itm_data_t), 1, fp);
1146 }
1147
1148 (void) fseek(fp, info_header->reg_plc_tbl.place.itm_ptr,
1149 SEEK_SET);
1150 TRACE_MESSAGE('P', ("reg_plc_tbl.place=%p:\n",
1151 info_header->reg_plc_tbl.place.itm_ptr));
1152
1153 for (name = name_first;
1154 name; name = name->next) {
1155 itm_data_t data;
1156 if ((ITMC_OBJ_REGISTER != name->type) ||
1157 (0 == name->name.size)) {
1158 continue;
1159 }
1160 #if !defined(_LP64)
1161 data.pad = 0;
1162 #endif
1163 data.size = name->name.size;
1164 if ((sizeof (itm_place_t)) < data.size) {
1165 #if !defined(_LP64)
1166 data.place.itm_pad = 0;
1167 #endif
1168 data.place.itm_ptr = name->reloc.itm_ptr;
1169 } else {
1170 data.place = name->name.place;
1171 }
1172 (void) fwrite(&data, sizeof (itm_data_t), 1, fp);
1173 }
1174
1175 /* Name section */
1176 (void) fseek(fp, info_header->name_sec.place.itm_ptr, SEEK_SET);
1177 TRACE_MESSAGE('P', ("name_sec.place=%p:\n",
1178 info_header->name_sec.place.itm_ptr));
1179 for (name = name_first, sec_size = 0;
1180 name; name = name->next) {
1181 if ((ITMC_OBJ_REGISTER == name->type) ||
1182 (name->name.size <= (sizeof (itm_place_t)))) {
1183 continue;
1184 }
1185 (void) fwrite(NSPTR(&(name->name)), 1,
1186 name->name.size, fp);
1187 sec_size += name->name.size;
1188 }
1189 for (name = name_first; name; name = name->next) {
1190 if ((ITMC_OBJ_REGISTER != name->type) ||
1191 (name->name.size <= (sizeof (itm_place_t)))) {
1192 continue;
1193 }
1194 (void) fwrite(NSPTR(&(name->name)), 1,
1195 name->name.size, fp);
1196 sec_size += name->name.size;
1197 }
1198 if (sec_size < info_header->name_sec.size) {
1199 (void) fwrite("\0\0\0\0", 1,
1200 info_header->name_sec.size - sec_size, fp);
1201 }
1202 }
1203 (void) fclose(fp);
1204 }
1205