xref: /illumos-gate/usr/src/cmd/geniconvtbl/assemble.c (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
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
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
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
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
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
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
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
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