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