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