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