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) 1988 AT&T 24 * All Rights Reserved 25 * 26 */ 27 28 /* 29 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 30 * Use is subject to license terms. 31 */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" 34 35 #include "mcs.h" 36 #include "extern.h" 37 #include "gelf.h" 38 39 /* 40 * Function prototypes. 41 */ 42 static void docompress(section_info_table *); 43 static char *compress(char *, size_t *); 44 static void doappend(char *, section_info_table *); 45 static void doprint(char *, section_info_table *); 46 static void dozap(section_info_table *); 47 static int dohash(char *); 48 49 50 51 /* 52 * Apply the actions specified by the user. 53 */ 54 int 55 apply_action(section_info_table *info, char *cur_file, Cmd_Info *cmd_info) 56 { 57 int act_index; 58 int ret = 0; 59 GElf_Shdr shdr; 60 61 (void) gelf_getshdr(info->scn, &shdr); 62 for (act_index = 0; act_index < actmax; act_index++) { 63 Action[act_index].a_cnt++; 64 switch (Action[act_index].a_action) { 65 case ACT_ZAP: 66 if (GET_ACTION(info->flags) == ACT_DELETE) 67 break; 68 dozap(info); 69 SET_ACTION(info->flags, ACT_ZAP); 70 SET_MODIFIED(info->flags); 71 break; 72 case ACT_PRINT: 73 if (GET_ACTION(info->flags) == ACT_DELETE) 74 break; 75 if (shdr.sh_type == SHT_NOBITS) { 76 error_message(ACT_PRINT_ERROR, 77 PLAIN_ERROR, (char *)0, 78 prog, cur_file, SECT_NAME); 79 break; 80 } 81 doprint(cur_file, info); 82 break; 83 case ACT_DELETE: 84 /* 85 * If I am strip command, this is the 86 * only action I can take. 87 */ 88 if (GET_ACTION(info->flags) == ACT_DELETE) 89 break; 90 if (GET_LOC(info->flags) == IN) { 91 /* 92 * If I am 'strip', I have to 93 * unset the candidate flag and 94 * unset the error return code. 95 */ 96 if (CHK_OPT(info, I_AM_STRIP)) { 97 ret = 0; 98 UNSET_CANDIDATE(info->flags); 99 } else { 100 ret++; 101 error_message(ACT_DELETE1_ERROR, 102 PLAIN_ERROR, (char *)0, 103 prog, cur_file, info->name); 104 } 105 break; 106 } else if (info->rel_loc == IN) { 107 /* 108 * If I am 'strip', I have to 109 * unset the candidate flag and 110 * unset the error return code. 111 */ 112 if (CHK_OPT(info, I_AM_STRIP)) { 113 ret = 0; 114 UNSET_CANDIDATE(info->flags); 115 } else { 116 ret++; 117 error_message(ACT_DELETE2_ERROR, 118 PLAIN_ERROR, (char *)0, 119 prog, cur_file, SECT_NAME, 120 info->rel_name); 121 } 122 break; 123 } else if (GET_LOC(info->flags) == PRIOR) { 124 /* 125 * I can not delete this 126 * section. I can only NULL 127 * this out. 128 */ 129 info->secno = (GElf_Word)NULLED; 130 (cmd_info->no_of_nulled)++; 131 } else { 132 info->secno = (GElf_Word)DELETED; 133 (cmd_info->no_of_delete)++; 134 } 135 SET_ACTION(info->flags, ACT_DELETE); 136 SET_MODIFIED(info->flags); 137 break; 138 case ACT_APPEND: 139 if (shdr.sh_type == SHT_NOBITS) { 140 ret++; 141 error_message(ACT_APPEND1_ERROR, 142 PLAIN_ERROR, (char *)0, 143 prog, cur_file, SECT_NAME); 144 break; 145 } else if (GET_LOC(info->flags) == IN) { 146 ret++; 147 error_message(ACT_APPEND2_ERROR, 148 PLAIN_ERROR, (char *)0, 149 prog, cur_file, SECT_NAME); 150 break; 151 } 152 doappend(Action[act_index].a_string, info); 153 (cmd_info->no_of_append)++; 154 info->secno = info->osecno; 155 SET_ACTION(info->flags, ACT_APPEND); 156 SET_MODIFIED(info->flags); 157 if (GET_LOC(info->flags) == PRIOR) 158 info->secno = (GElf_Word)EXPANDED; 159 break; 160 case ACT_COMPRESS: 161 /* 162 * If this section is already deleted, 163 * don't do anything. 164 */ 165 if (GET_ACTION(info->flags) == ACT_DELETE) 166 break; 167 if (shdr.sh_type == SHT_NOBITS) { 168 ret++; 169 error_message(ACT_COMPRESS1_ERROR, 170 PLAIN_ERROR, (char *)0, 171 prog, cur_file, SECT_NAME); 172 break; 173 } else if (GET_LOC(info->flags) == IN) { 174 ret++; 175 error_message(ACT_COMPRESS2_ERROR, 176 PLAIN_ERROR, (char *)0, 177 prog, cur_file, SECT_NAME); 178 break; 179 } 180 181 docompress(info); 182 (cmd_info->no_of_compressed)++; 183 SET_ACTION(info->flags, ACT_COMPRESS); 184 SET_MODIFIED(info->flags); 185 if (GET_LOC(info->flags) == PRIOR) 186 info->secno = (GElf_Word)SHRUNK; 187 break; 188 } 189 } 190 return (ret); 191 } 192 193 /* 194 * ACT_ZAP 195 */ 196 static void 197 dozap(section_info_table *info) 198 { 199 Elf_Data *data; 200 201 info->mdata = data = malloc(sizeof (Elf_Data)); 202 if (data == NULL) { 203 error_message(MALLOC_ERROR, 204 PLAIN_ERROR, (char *)0, 205 prog); 206 exit(1); 207 } 208 *data = *info->data; 209 data->d_buf = calloc(1, data->d_size); 210 if (data->d_buf == NULL) { 211 error_message(MALLOC_ERROR, 212 PLAIN_ERROR, (char *)0, 213 prog); 214 exit(1); 215 } 216 } 217 218 /* 219 * ACT_PRINT 220 */ 221 static void 222 doprint(char *cur_file, section_info_table *info) 223 { 224 Elf_Data *data; 225 size_t temp_size; 226 char *temp_string; 227 228 if (GET_MODIFIED(info->flags) == 0) 229 data = info->data; 230 else 231 data = info->mdata; 232 if (data == 0) 233 return; 234 235 temp_size = data->d_size; 236 temp_string = data->d_buf; 237 238 if (temp_size == 0) 239 return; 240 (void) fprintf(stdout, "%s:\n", cur_file); 241 242 while (temp_size--) { 243 char c = *temp_string++; 244 switch (c) { 245 case '\0': 246 (void) putchar('\n'); 247 break; 248 default: 249 (void) putchar(c); 250 break; 251 } 252 } 253 (void) putchar('\n'); 254 } 255 256 /* 257 * ACT_APPEND 258 */ 259 static void 260 doappend(char *a_string, section_info_table *info) 261 { 262 Elf_Data *data; 263 char *p; 264 size_t len; 265 char *tp; 266 267 /* 268 * Get the length of the string to be added. 269 */ 270 len = strlen(a_string); 271 if (len == 0) 272 return; 273 274 /* 275 * Every modification operation will be done 276 * to a new Elf_Data descriptor. 277 */ 278 if (info->mdata == 0) { 279 /* 280 * mdata is not allocated yet. 281 * Allocate the data and set it. 282 */ 283 info->mdata = data = calloc(1, sizeof (Elf_Data)); 284 if (data == NULL) { 285 error_message(MALLOC_ERROR, 286 PLAIN_ERROR, (char *)0, 287 prog); 288 exit(1); 289 } 290 *data = *info->data; 291 292 /* 293 * Check if the section is deleted or not. 294 * Or if the size is 0 or not. 295 */ 296 if ((GET_ACTION(info->flags) == ACT_DELETE) || 297 data->d_size == 0) { 298 /* 299 * The section was deleated. 300 * But now, the user wants to add data to this 301 * section. 302 */ 303 data->d_buf = calloc(1, len + 2); 304 if (data->d_buf == 0) { 305 error_message(MALLOC_ERROR, 306 PLAIN_ERROR, (char *)0, 307 prog); 308 exit(1); 309 } 310 tp = (char *)data->d_buf; 311 (void) memcpy(& tp[1], a_string, len + 1); 312 data->d_size = len + 2; 313 } else { 314 /* 315 * The user wants to add data to the section. 316 * I am not going to change the original data. 317 * Do the modification on the new one. 318 */ 319 p = malloc(len + 1 + data->d_size); 320 if (p == NULL) { 321 error_message(MALLOC_ERROR, 322 PLAIN_ERROR, (char *)0, 323 prog); 324 exit(1); 325 } 326 (void) memcpy(p, data->d_buf, data->d_size); 327 (void) memcpy(&p[data->d_size], a_string, len + 1); 328 data->d_buf = p; 329 data->d_size = data->d_size + len + 1; 330 } 331 } else { 332 /* 333 * mdata is already allocated. 334 * Modify it. 335 */ 336 data = info->mdata; 337 if ((GET_ACTION(info->flags) == ACT_DELETE) || 338 data->d_size == 0) { 339 /* 340 * The section was deleated. 341 * But now, the user wants to add data to this 342 * section. 343 */ 344 if (data->d_buf) 345 free(data->d_buf); 346 data->d_buf = calloc(1, len + 2); 347 if (data->d_buf == 0) { 348 error_message(MALLOC_ERROR, 349 PLAIN_ERROR, (char *)0, 350 prog); 351 exit(1); 352 } 353 tp = (char *)data->d_buf; 354 (void) memcpy(&tp[1], a_string, len + 1); 355 data->d_size = len + 2; 356 } else { 357 /* 358 * The user wants to add data to the section. 359 * I am not going to change the original data. 360 * Do the modification on the new one. 361 */ 362 p = malloc(len + 1 + data->d_size); 363 if (p == NULL) { 364 error_message(MALLOC_ERROR, 365 PLAIN_ERROR, (char *)0, 366 prog); 367 exit(1); 368 } 369 (void) memcpy(p, data->d_buf, data->d_size); 370 (void) memcpy(&p[data->d_size], a_string, len + 1); 371 free(data->d_buf); 372 data->d_buf = p; 373 data->d_size = data->d_size + len + 1; 374 } 375 } 376 } 377 378 /* 379 * ACT_COMPRESS 380 */ 381 #define HALFLONG 16 382 #define low(x) (x&((1L<<HALFLONG)-1)) 383 #define high(x) (x>>HALFLONG) 384 385 static void 386 docompress(section_info_table *info) 387 { 388 Elf_Data *data; 389 size_t size; 390 char *buf; 391 392 if (info->mdata == 0) { 393 /* 394 * mdata is not allocated yet. 395 * Allocate the data and set it. 396 */ 397 char *p; 398 info->mdata = data = calloc(1, sizeof (Elf_Data)); 399 if (data == NULL) { 400 error_message(MALLOC_ERROR, 401 PLAIN_ERROR, (char *)0, 402 prog); 403 exit(1); 404 } 405 *data = *info->data; 406 p = malloc(data->d_size); 407 (void) memcpy(p, (char *)data->d_buf, data->d_size); 408 data->d_buf = p; 409 } 410 size = info->mdata->d_size; 411 buf = (char *)info->mdata->d_buf; 412 buf = compress(buf, &size); 413 info->mdata->d_buf = buf; 414 info->mdata->d_size = size; 415 } 416 417 static char * 418 compress(char *str, size_t *size) 419 { 420 int hash; 421 int i; 422 size_t temp_string_size = 0; 423 size_t o_size = *size; 424 char *temp_string = str; 425 426 int *hash_key; 427 size_t hash_num; 428 size_t hash_end; 429 size_t *hash_str; 430 char *strings; 431 size_t next_str; 432 size_t str_size; 433 434 hash_key = malloc(sizeof (int) * 200); 435 hash_end = 200; 436 hash_str = malloc(sizeof (size_t) * 200); 437 str_size = o_size+1; 438 strings = malloc(str_size); 439 440 if (hash_key == NULL || hash_str == NULL || strings == NULL) { 441 error_message(MALLOC_ERROR, 442 PLAIN_ERROR, (char *)0, 443 prog); 444 mcs_exit(FAILURE); 445 } 446 447 hash_num = 0; 448 next_str = 0; 449 450 while (temp_string_size < o_size) { 451 size_t pos; 452 char c; 453 /* 454 * Get a string 455 */ 456 pos = next_str; 457 458 while ((c = *(temp_string++)) != '\0' && 459 (temp_string_size + (next_str - pos)) <= o_size) { 460 if (next_str >= str_size) { 461 str_size *= 2; 462 if ((strings = (char *) 463 realloc(strings, str_size)) == NULL) { 464 error_message(MALLOC_ERROR, 465 PLAIN_ERROR, (char *)0, 466 prog); 467 mcs_exit(FAILURE); 468 } 469 } 470 strings[next_str++] = c; 471 } 472 473 if (next_str >= str_size) { 474 str_size *= 2; 475 if ((strings = (char *) 476 realloc(strings, str_size)) == NULL) { 477 error_message(MALLOC_ERROR, 478 PLAIN_ERROR, (char *)0, 479 prog); 480 mcs_exit(FAILURE); 481 } 482 } 483 strings[next_str++] = NULL; 484 /* 485 * End get string 486 */ 487 488 temp_string_size += (next_str - pos); 489 hash = dohash(pos + strings); 490 for (i = 0; i < hash_num; i++) { 491 if (hash != hash_key[i]) 492 continue; 493 if (strcmp(pos + strings, hash_str[i] + strings) == 0) 494 break; 495 } 496 if (i != hash_num) { 497 next_str = pos; 498 continue; 499 } 500 if (hash_num == hash_end) { 501 hash_end *= 2; 502 hash_key = realloc((char *)hash_key, 503 hash_end * sizeof (int)); 504 hash_str = realloc((char *)hash_str, 505 hash_end * sizeof (size_t)); 506 if (hash_key == NULL || hash_str == NULL) { 507 error_message(MALLOC_ERROR, 508 PLAIN_ERROR, (char *)0, 509 prog); 510 mcs_exit(FAILURE); 511 } 512 } 513 hash_key[hash_num] = hash; 514 hash_str[hash_num++] = pos; 515 } 516 517 /* 518 * Clean up 519 */ 520 free(hash_key); 521 free(hash_str); 522 523 /* 524 * Return 525 */ 526 if (next_str != o_size) { 527 /* 528 * string compressed. 529 */ 530 *size = next_str; 531 free(str); 532 str = malloc(next_str); 533 (void) memcpy(str, strings, next_str); 534 } 535 free(strings); 536 return (str); 537 } 538 539 static int 540 dohash(char *str) 541 { 542 long sum; 543 unsigned shift; 544 int t; 545 sum = 1; 546 for (shift = 0; (t = *str++) != NULL; shift += 7) { 547 sum += (long)t << (shift %= HALFLONG); 548 } 549 sum = low(sum) + high(sum); 550 /* LINTED */ 551 return ((short)low(sum) + (short)high(sum)); 552 } 553 554 /* 555 * Append an item to the specified list, and return a pointer to the list 556 * node created. 557 */ 558 Listnode * 559 list_appendc(List *lst, const void *item) 560 { 561 Listnode *_lnp; 562 563 if ((_lnp = malloc(sizeof (Listnode))) == (Listnode *)0) 564 return (0); 565 566 _lnp->data = (void *)item; 567 _lnp->next = NULL; 568 569 if (lst->head == NULL) 570 lst->tail = lst->head = _lnp; 571 else { 572 lst->tail->next = _lnp; 573 lst->tail = lst->tail->next; 574 } 575 return (_lnp); 576 } 577