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
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
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
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
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
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
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
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