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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <errno.h> 32 #include "mcs.h" 33 #include "extern.h" 34 #include "gelf.h" 35 36 /* 37 * Type used to pass state information for the current 38 * file between routines. 39 */ 40 typedef struct { 41 int Sect_exists; 42 int notesegndx; 43 int notesctndx; 44 Seg_Table *b_e_seg_table; 45 section_info_table *sec_table; 46 int64_t *off_table; /* maintains section's offset; set to */ 47 /* retain old offset, else 0 */ 48 int64_t *nobits_table; /* maintains NOBITS sections */ 49 char *new_sec_string; 50 } file_state_t; 51 52 53 /* 54 * Function prototypes. 55 */ 56 static void copy_file(int, char *, char *); 57 static void 58 copy_non_elf_to_temp_ar(int, Elf *, int, Elf_Arhdr *, char *, Cmd_Info *); 59 static void copy_elf_file_to_temp_ar_file(int, Elf_Arhdr *, char *); 60 static int process_file(Elf *, char *, Cmd_Info *); 61 static void initialize(int shnum, Cmd_Info *, file_state_t *); 62 static int build_segment_table(Elf*, GElf_Ehdr *, file_state_t *); 63 static int traverse_file(Elf *, GElf_Ehdr *, char *, Cmd_Info *, 64 file_state_t *); 65 static uint64_t location(int64_t, int, Elf *, file_state_t *); 66 static uint64_t scn_location(Elf_Scn *, Elf *, file_state_t *); 67 static int build_file(Elf *, GElf_Ehdr *, Cmd_Info *, file_state_t *); 68 static void post_process(Cmd_Info *, file_state_t *); 69 70 71 72 int 73 each_file(char *cur_file, Cmd_Info *cmd_info) 74 { 75 Elf *elf = 0; 76 Elf_Cmd cmd; 77 Elf *arf = 0; 78 Elf_Arhdr *mem_header; 79 char *cur_filenm = NULL; 80 int code = 0; 81 int error = 0, err = 0; 82 int ar_file = 0; 83 int fdartmp; 84 int fd; 85 int oflag; 86 87 if (cmd_info->flags & MIGHT_CHG) 88 oflag = O_RDWR; 89 else 90 oflag = O_RDONLY; 91 92 if ((fd = open(cur_file, oflag)) == -1) { 93 error_message(OPEN_ERROR, SYSTEM_ERROR, strerror(errno), 94 prog, cur_file); 95 return (FAILURE); 96 } 97 98 /* 99 * Note, elf_begin requires ELF_C_READ even if MIGHT_CHK is in effect. 100 * libelf does not allow elf_begin() with ELF_C_RDWR when processing 101 * archive file members. Because we are limited to ELF_C_READ use, any 102 * ELF data modification must be provided by updating a copy of 103 * the data, rather than updating the original file data. 104 */ 105 cmd = ELF_C_READ; 106 if ((arf = elf_begin(fd, cmd, (Elf *)0)) == 0) { 107 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 108 (void) elf_end(arf); 109 (void) close(fd); /* done processing this file */ 110 return (FAILURE); 111 } 112 113 if ((elf_kind(arf) == ELF_K_AR)) { 114 ar_file = 1; 115 if (CHK_OPT(cmd_info, MIGHT_CHG)) { 116 artmpfile = tempnam(TMPDIR, "mcs2"); 117 if ((fdartmp = open(artmpfile, 118 O_WRONLY | O_APPEND | O_CREAT, 119 (mode_t)0666)) == NULL) { 120 error_message(OPEN_TEMP_ERROR, 121 SYSTEM_ERROR, strerror(errno), 122 prog, artmpfile); 123 (void) elf_end(arf); 124 (void) close(fd); 125 exit(FAILURE); 126 } 127 /* write magic string to artmpfile */ 128 if ((write(fdartmp, ARMAG, SARMAG)) != SARMAG) { 129 error_message(WRITE_ERROR, 130 SYSTEM_ERROR, strerror(errno), 131 prog, artmpfile, cur_file); 132 mcs_exit(FAILURE); 133 } 134 } 135 } else { 136 ar_file = 0; 137 cur_filenm = cur_file; 138 } 139 140 /* 141 * Holds temporary file; 142 * if archive, holds the current member file if it has an ehdr, 143 * and there were no errors in 144 * processing the object file. 145 */ 146 elftmpfile = tempnam(TMPDIR, "mcs1"); 147 148 while ((elf = elf_begin(fd, cmd, arf)) != 0) { 149 if (ar_file) /* get header info */ { 150 size_t len; 151 152 if ((mem_header = elf_getarhdr(elf)) == NULL) { 153 error_message(GETARHDR_ERROR, LIBelf_ERROR, 154 elf_errmsg(-1), prog, cur_file, 155 elf_getbase(elf)); 156 (void) elf_end(elf); 157 (void) elf_end(arf); 158 (void) close(fd); 159 (void) unlink(artmpfile); 160 return (FAILURE); 161 } 162 163 if (cur_filenm != NULL) 164 free(cur_filenm); 165 166 len = (strlen(cur_file) + 3 + 167 strlen(mem_header->ar_name)); 168 169 if ((cur_filenm = malloc(len)) == NULL) { 170 error_message(MALLOC_ERROR, 171 PLAIN_ERROR, (char *)0, prog); 172 mcs_exit(FAILURE); 173 } 174 175 (void) snprintf(cur_filenm, len, "%s[%s]", 176 cur_file, mem_header->ar_name); 177 } 178 179 if (elf_kind(elf) == ELF_K_ELF) { 180 if ((code = process_file(elf, cur_filenm, cmd_info)) == 181 FAILURE) { 182 if (!ar_file) { 183 (void) elf_end(arf); 184 (void) elf_end(elf); 185 (void) close(fd); 186 return (FAILURE); 187 } else { 188 copy_non_elf_to_temp_ar(fd, elf, 189 fdartmp, mem_header, 190 cur_file, cmd_info); 191 error++; 192 } 193 } else if (ar_file && CHK_OPT(cmd_info, MIGHT_CHG)) { 194 if (code == DONT_BUILD) 195 copy_non_elf_to_temp_ar(fd, elf, 196 fdartmp, mem_header, 197 cur_file, cmd_info); 198 else 199 copy_elf_file_to_temp_ar_file( 200 fdartmp, mem_header, cur_file); 201 } 202 } else { 203 /* 204 * decide what to do with non-ELF file 205 */ 206 if (!ar_file) { 207 error_message(FILE_TYPE_ERROR, PLAIN_ERROR, 208 (char *)0, prog, cur_filenm); 209 (void) close(fd); 210 return (FAILURE); 211 } else { 212 if (CHK_OPT(cmd_info, MIGHT_CHG)) 213 copy_non_elf_to_temp_ar(fd, elf, 214 fdartmp, mem_header, 215 cur_file, cmd_info); 216 } 217 } 218 cmd = elf_next(elf); 219 (void) elf_end(elf); 220 } 221 222 err = elf_errno(); 223 if (err != 0) { 224 error_message(LIBELF_ERROR, LIBelf_ERROR, 225 elf_errmsg(err), prog); 226 error_message(NOT_MANIPULATED_ERROR, PLAIN_ERROR, (char *)0, 227 prog, cur_file); 228 return (FAILURE); 229 } 230 231 (void) elf_end(arf); 232 233 if (ar_file && CHK_OPT(cmd_info, MIGHT_CHG)) { 234 (void) close(fdartmp); /* done writing to ar_temp_file */ 235 /* copy ar_temp_file to FILE */ 236 copy_file(fd, cur_file, artmpfile); 237 } else if (code != DONT_BUILD && CHK_OPT(cmd_info, MIGHT_CHG)) 238 copy_file(fd, cur_file, elftmpfile); 239 (void) close(fd); /* done processing this file */ 240 return (error); 241 } 242 243 static int 244 process_file(Elf *elf, char *cur_file, Cmd_Info *cmd_info) 245 { 246 int error = SUCCESS; 247 int x; 248 GElf_Ehdr ehdr; 249 size_t shnum; 250 file_state_t state; 251 252 /* 253 * Initialize 254 */ 255 if (gelf_getehdr(elf, &ehdr) == NULL) { 256 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 257 return (FAILURE); 258 } 259 260 if (elf_getshnum(elf, &shnum) == NULL) { 261 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 262 return (FAILURE); 263 } 264 265 /* Initialize per-file state */ 266 state.Sect_exists = 0; 267 state.notesegndx = -1; 268 state.notesctndx = -1; 269 state.b_e_seg_table = NULL; 270 state.sec_table = NULL; 271 state.off_table = 0; 272 state.nobits_table = NULL; 273 state.new_sec_string = NULL; 274 275 initialize(shnum, cmd_info, &state); 276 277 if ((ehdr.e_phnum != 0) && 278 (build_segment_table(elf, &ehdr, &state) == FAILURE)) { 279 x = error = FAILURE; 280 } else if ((x = traverse_file(elf, &ehdr, cur_file, 281 cmd_info, &state)) == FAILURE) { 282 error_message(WRN_MANIPULATED_ERROR, PLAIN_ERROR, (char *)0, 283 prog, cur_file); 284 error = FAILURE; 285 } else if (x != DONT_BUILD && x != FAILURE) { 286 post_process(cmd_info, &state); 287 if (build_file(elf, &ehdr, cmd_info, &state) == FAILURE) { 288 error_message(WRN_MANIPULATED_ERROR, PLAIN_ERROR, 289 (char *)0, prog, cur_file); 290 error = FAILURE; 291 } 292 } 293 294 /* Release any dynamicaly allocated buffers */ 295 if (state.b_e_seg_table != NULL) 296 free(state.b_e_seg_table); 297 if (state.sec_table != NULL) 298 free(state.sec_table); 299 if (state.off_table != NULL) 300 free(state.off_table); 301 if (state.nobits_table != NULL) 302 free(state.nobits_table); 303 if (state.new_sec_string != NULL) 304 free(state.new_sec_string); 305 306 if (x == DONT_BUILD) 307 return (DONT_BUILD); 308 else 309 return (error); 310 } 311 312 static int 313 traverse_file(Elf *elf, GElf_Ehdr * ehdr, char *cur_file, Cmd_Info *cmd_info, 314 file_state_t *state) 315 { 316 Elf_Scn * scn; 317 Elf_Scn * temp_scn; 318 Elf_Data * data; 319 GElf_Shdr * shdr; 320 char *temp_name; 321 section_info_table * sinfo; 322 GElf_Xword x; 323 int ret = 0, SYM = 0; /* used by strip command */ 324 int phnum = ehdr->e_phnum; 325 unsigned int i, scn_index; 326 size_t shstrndx, shnum; 327 328 state->Sect_exists = 0; 329 330 if (elf_getshnum(elf, &shnum) == NULL) { 331 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 332 return (FAILURE); 333 } 334 if (elf_getshstrndx(elf, &shstrndx) == NULL) { 335 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 336 return (FAILURE); 337 } 338 339 scn = 0; 340 scn_index = 1; 341 sinfo = &state->sec_table[scn_index]; 342 while ((scn = elf_nextscn(elf, scn)) != 0) { 343 char *name; 344 345 shdr = &(sinfo->shdr); 346 if (gelf_getshdr(scn, shdr) == NULL) { 347 error_message(NO_SECT_TABLE_ERROR, 348 LIBelf_ERROR, elf_errmsg(-1), prog, cur_file); 349 return (FAILURE); 350 } 351 352 /* 353 * Note: If the object has problems, name 354 * may be set to NULL by the following. 355 */ 356 name = elf_strptr(elf, shstrndx, (size_t)shdr->sh_name); 357 358 sinfo->scn = scn; 359 sinfo->secno = scn_index; 360 sinfo->osecno = scn_index; 361 SET_ACTION(sinfo->flags, ACT_NOP); 362 sinfo->name = name; 363 if (ehdr->e_phnum == 0) 364 SET_LOC(sinfo->flags, NOSEG); 365 else 366 SET_LOC(sinfo->flags, scn_location(scn, elf, state)); 367 368 if (shdr->sh_type == SHT_GROUP) { 369 if (list_appendc(&cmd_info->sh_groups, sinfo) == 0) { 370 error_message(MALLOC_ERROR, PLAIN_ERROR, 371 (char *)0, prog); 372 mcs_exit(FAILURE); 373 } 374 } 375 376 /* 377 * If the target section is pointed by a section 378 * holding relocation infomation, then the 379 * pointing section would be useless if the 380 * target section is removed. 381 */ 382 if ((shdr->sh_type == SHT_REL || 383 shdr->sh_type == SHT_RELA) && 384 (shdr->sh_info != SHN_UNDEF && 385 (temp_scn = elf_getscn(elf, shdr->sh_info)) != 0)) { 386 GElf_Shdr tmp_shdr; 387 if (gelf_getshdr(temp_scn, &tmp_shdr) != NULL) { 388 temp_name = elf_strptr(elf, shstrndx, 389 (size_t)tmp_shdr.sh_name); 390 sinfo->rel_name = temp_name; 391 sinfo->rel_scn_index = 392 shdr->sh_info; 393 if (phnum == 0) 394 sinfo->rel_loc = NOSEG; 395 else 396 sinfo->rel_loc = 397 scn_location(temp_scn, elf, state); 398 } 399 } 400 data = 0; 401 if ((data = elf_getdata(scn, data)) == NULL) { 402 error_message(LIBELF_ERROR, 403 LIBelf_ERROR, elf_errmsg(-1), prog); 404 return (FAILURE); 405 } 406 sinfo->data = data; 407 408 /* 409 * Check if this section is a candidate for 410 * action to be processes. 411 */ 412 if ((name != NULL) && (sectcmp(name) == 0)) { 413 SET_CANDIDATE(sinfo->flags); 414 415 /* 416 * This flag just shows that there was a 417 * candidate. 418 */ 419 state->Sect_exists++; 420 } 421 422 /* 423 * Any of the following section types should 424 * also be removed (if possible) if invoked via 425 * the 'strip' command. 426 */ 427 if (CHK_OPT(cmd_info, I_AM_STRIP) && 428 ((shdr->sh_type == SHT_SUNW_DEBUG) || 429 (shdr->sh_type == SHT_SUNW_DEBUGSTR))) { 430 SET_CANDIDATE(sinfo->flags); 431 state->Sect_exists++; 432 } 433 434 435 /* 436 * Zap this file ? 437 */ 438 if ((cmd_info->flags & zFLAG) && 439 (shdr->sh_type == SHT_PROGBITS)) { 440 SET_CANDIDATE(sinfo->flags); 441 state->Sect_exists++; 442 } 443 x = GET_LOC(sinfo->flags); 444 445 /* 446 * Remember the note section index so that we can 447 * reset the NOTE segment offset to point to it. Depending 448 * on the operation being carried out, the note section may 449 * be assigned a new location in the resulting ELF 450 * image, and the program header needs to reflect that. 451 * 452 * There can be multiple contiguous note sections in 453 * an object, referenced by a single NOTE segment. We 454 * want to be sure and remember the one referenced by 455 * the program header, and not one of the others. 456 */ 457 if ((shdr->sh_type == SHT_NOTE) && (state->notesctndx == -1) && 458 (state->notesegndx != -1) && 459 (state->b_e_seg_table[state->notesegndx].p_offset 460 == shdr->sh_offset)) 461 state->notesctndx = scn_index; 462 463 if (x == IN || x == PRIOR) 464 state->off_table[scn_index] = shdr->sh_offset; 465 if (shdr->sh_type == SHT_NOBITS) 466 state->nobits_table[scn_index] = 1; 467 468 /* 469 * If this section satisfies the condition, 470 * apply the actions specified. 471 */ 472 if (ISCANDIDATE(sinfo->flags)) { 473 ret += apply_action(sinfo, cur_file, cmd_info); 474 } 475 476 /* 477 * If I am strip command, determine if symtab can go or not. 478 */ 479 if (CHK_OPT(cmd_info, I_AM_STRIP) && 480 (CHK_OPT(cmd_info, xFLAG) == 0) && 481 (CHK_OPT(cmd_info, lFLAG) == 0)) { 482 if (shdr->sh_type == SHT_SYMTAB && 483 GET_LOC(sinfo->flags) == AFTER) { 484 SYM = scn_index; 485 } 486 } 487 scn_index++; 488 sinfo++; 489 } 490 sinfo->scn = (Elf_Scn *) -1; 491 492 /* 493 * If there were any errors traversing the file, 494 * just return error. 495 */ 496 if (ret != 0) 497 return (FAILURE); 498 499 /* 500 * Remove symbol table if possible 501 */ 502 if (CHK_OPT(cmd_info, I_AM_STRIP) && SYM != 0) { 503 GElf_Shdr tmp_shdr; 504 505 (void) gelf_getshdr(state->sec_table[SYM].scn, &tmp_shdr); 506 state->sec_table[SYM].secno = (GElf_Word)DELETED; 507 ++(cmd_info->no_of_nulled); 508 if (state->Sect_exists == 0) 509 ++state->Sect_exists; 510 SET_ACTION(state->sec_table[SYM].flags, ACT_DELETE); 511 state->off_table[SYM] = 0; 512 /* 513 * Can I remove section header 514 * string table ? 515 */ 516 if ((tmp_shdr.sh_link < shnum) && 517 (tmp_shdr.sh_link != SHN_UNDEF) && 518 (tmp_shdr.sh_link != shstrndx) && 519 (GET_LOC(state->sec_table[tmp_shdr.sh_link].flags) == 520 AFTER)) { 521 state->sec_table[tmp_shdr.sh_link].secno = 522 (GElf_Word)DELETED; 523 ++(cmd_info->no_of_nulled); 524 if (state->Sect_exists == 0) 525 ++state->Sect_exists; 526 SET_ACTION(state->sec_table[tmp_shdr.sh_link].flags, 527 ACT_DELETE); 528 state->off_table[tmp_shdr.sh_link] = 0; 529 } 530 } 531 532 /* 533 * If I only printed the contents, then 534 * just report so. 535 */ 536 if (CHK_OPT(cmd_info, pFLAG) && !CHK_OPT(cmd_info, MIGHT_CHG)) 537 return (DONT_BUILD); /* don't bother creating a new file */ 538 /* since the file has not changed */ 539 540 /* 541 * I might need to add a new section. Check it. 542 */ 543 if (state->Sect_exists == 0 && CHK_OPT(cmd_info, aFLAG)) { 544 int act = 0; 545 state->new_sec_string = calloc(1, cmd_info->str_size + 1); 546 if (state->new_sec_string == NULL) 547 return (FAILURE); 548 for (act = 0; act < actmax; act++) { 549 if (Action[act].a_action == ACT_APPEND) { 550 (void) strcat(state->new_sec_string, 551 Action[act].a_string); 552 (void) strcat(state->new_sec_string, "\n"); 553 cmd_info->no_of_append = 1; 554 } 555 } 556 } 557 558 /* 559 * If I did not append any new sections, and I did not 560 * modify/delete any sections, then just report so. 561 */ 562 if ((state->Sect_exists == 0 && cmd_info->no_of_append == 0) || 563 !CHK_OPT(cmd_info, MIGHT_CHG)) 564 return (DONT_BUILD); 565 566 /* 567 * Found at least one section which was processed. 568 * Deleted or Appended or Compressed. 569 */ 570 if (state->Sect_exists) { 571 /* 572 * First, handle the deleted sections. 573 */ 574 if (cmd_info->no_of_delete != 0 || 575 cmd_info->no_of_nulled != 0) { 576 int acc = 0; 577 int rel_idx; 578 579 /* 580 * Handle relocation/target 581 * sections. 582 */ 583 sinfo = &(state->sec_table[0]); 584 for (i = 1; i < shnum; i++) { 585 sinfo++; 586 rel_idx = sinfo->rel_scn_index; 587 if (rel_idx == 0) 588 continue; 589 590 /* 591 * If I am removed, then remove my 592 * target section. 593 */ 594 if (((sinfo->secno == 595 (GElf_Word)DELETED) || 596 (sinfo->secno == 597 (GElf_Word)NULLED)) && 598 sinfo->rel_loc != IN) { 599 if (GET_LOC(state-> 600 sec_table[rel_idx].flags) == PRIOR) 601 state->sec_table[rel_idx]. 602 secno = (GElf_Word)NULLED; 603 else 604 state->sec_table[rel_idx]. 605 secno = (GElf_Word)DELETED; 606 SET_ACTION(state->sec_table[rel_idx]. 607 flags, ACT_DELETE); 608 } 609 610 /* 611 * I am not removed. Check if my target is 612 * removed or nulled. If so, let me try to 613 * remove my self. 614 */ 615 if (((state->sec_table[rel_idx].secno == 616 (GElf_Word)DELETED) || 617 (state->sec_table[rel_idx].secno == 618 (GElf_Word)NULLED)) && 619 (GET_LOC(sinfo->flags) != IN)) { 620 if (GET_LOC(sinfo->flags) == 621 PRIOR) 622 sinfo->secno = 623 (GElf_Word)NULLED; 624 else 625 sinfo->secno = 626 (GElf_Word)DELETED; 627 SET_ACTION(sinfo->flags, ACT_DELETE); 628 } 629 } 630 631 /* 632 * Now, take care of DELETED sections 633 */ 634 sinfo = &(state->sec_table[1]); 635 for (i = 1; i < shnum; i++) { 636 shdr = &(sinfo->shdr); 637 if (sinfo->secno == (GElf_Word)DELETED) { 638 acc++; 639 /* 640 * The SHT_GROUP section which this 641 * section is a member may be able 642 * to be removed. See post_process(). 643 */ 644 if (shdr->sh_flags & SHF_GROUP) 645 cmd_info->flags |= 646 SHF_GROUP_DEL; 647 } else { 648 /* 649 * The data buffer of SHT_GROUP this 650 * section is a member needs to be 651 * updated. See post_process(). 652 */ 653 sinfo->secno -= acc; 654 if ((shdr->sh_flags & SHF_GROUP) && 655 (acc != 0)) 656 cmd_info->flags |= 657 SHF_GROUP_MOVE; 658 } 659 sinfo++; 660 } 661 } 662 } 663 664 /* 665 * I know that the file has been modified. 666 * A new file need to be created. 667 */ 668 return (SUCCESS); 669 } 670 671 static int 672 build_file(Elf *src_elf, GElf_Ehdr *src_ehdr, Cmd_Info *cmd_info, 673 file_state_t *state) 674 { 675 Elf_Scn *src_scn; 676 Elf_Scn *dst_scn; 677 int new_sh_name = 0; /* to hold the offset for the new */ 678 /* section's name */ 679 Elf *dst_elf = 0; 680 Elf_Data *elf_data; 681 Elf_Data *data; 682 int64_t scn_no, x; 683 size_t no_of_symbols = 0; 684 section_info_table *info; 685 unsigned int c = 0; 686 int fdtmp; 687 GElf_Shdr src_shdr; 688 GElf_Shdr dst_shdr; 689 GElf_Ehdr dst_ehdr; 690 GElf_Off new_offset = 0, r; 691 size_t shnum, shstrndx; 692 693 694 if (elf_getshnum(src_elf, &shnum) == NULL) { 695 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 696 return (FAILURE); 697 } 698 if (elf_getshstrndx(src_elf, &shstrndx) == NULL) { 699 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 700 return (FAILURE); 701 } 702 703 if ((fdtmp = open(elftmpfile, O_RDWR | O_TRUNC | O_CREAT, 704 (mode_t)0666)) == -1) { 705 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno), 706 prog, elftmpfile); 707 return (FAILURE); 708 } 709 710 if ((dst_elf = elf_begin(fdtmp, ELF_C_WRITE, (Elf *) 0)) == NULL) { 711 error_message(READ_ERROR, LIBelf_ERROR, elf_errmsg(-1), 712 prog, elftmpfile); 713 (void) close(fdtmp); 714 return (FAILURE); 715 } 716 717 if (gelf_newehdr(dst_elf, gelf_getclass(src_elf)) == NULL) { 718 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 719 return (FAILURE); 720 } 721 722 /* initialize dst_ehdr */ 723 (void) gelf_getehdr(dst_elf, &dst_ehdr); 724 dst_ehdr = *src_ehdr; 725 726 /* 727 * If we are removing the header string table section, 728 * remove the reference to it from the ELF header. 729 */ 730 if ((shstrndx != SHN_UNDEF) && 731 (state->sec_table[shstrndx].secno == (GElf_Word)DELETED)) 732 dst_ehdr.e_shstrndx = SHN_UNDEF; 733 734 /* 735 * flush the changes to the ehdr so the ident 736 * array and header string table index are filled in. 737 */ 738 (void) gelf_update_ehdr(dst_elf, &dst_ehdr); 739 740 741 if (src_ehdr->e_phnum != 0) { 742 (void) elf_flagelf(dst_elf, ELF_C_SET, ELF_F_LAYOUT); 743 744 if (gelf_newphdr(dst_elf, src_ehdr->e_phnum) == NULL) { 745 error_message(LIBELF_ERROR, LIBelf_ERROR, 746 elf_errmsg(-1), prog); 747 return (FAILURE); 748 } 749 750 for (x = 0; x < src_ehdr->e_phnum; ++x) { 751 GElf_Phdr dst; 752 GElf_Phdr src; 753 754 /* LINTED */ 755 (void) gelf_getphdr(src_elf, (int)x, &src); 756 /* LINTED */ 757 (void) gelf_getphdr(dst_elf, (int)x, &dst); 758 (void) memcpy(&dst, &src, sizeof (GElf_Phdr)); 759 /* LINTED */ 760 (void) gelf_update_phdr(dst_elf, (int)x, &dst); 761 } 762 763 x = location(dst_ehdr.e_phoff, 0, src_elf, state); 764 if (x == AFTER) 765 new_offset = (GElf_Off)src_ehdr->e_ehsize; 766 } 767 768 scn_no = 1; 769 while ((src_scn = state->sec_table[scn_no].scn) != (Elf_Scn *) -1) { 770 info = &state->sec_table[scn_no]; 771 /* If section should be copied to new file NOW */ 772 if ((info->secno != (GElf_Word)DELETED) && 773 info->secno <= scn_no) { 774 if ((dst_scn = elf_newscn(dst_elf)) == NULL) { 775 error_message(LIBELF_ERROR, 776 LIBelf_ERROR, elf_errmsg(-1), prog); 777 return (FAILURE); 778 } 779 (void) gelf_getshdr(dst_scn, &dst_shdr); 780 (void) gelf_getshdr(info->scn, &src_shdr); 781 (void) memcpy(&dst_shdr, &src_shdr, sizeof (GElf_Shdr)); 782 783 /* 784 * Update link and info fields 785 * The sh_link field may have special values so 786 * check them first. 787 */ 788 if ((src_shdr.sh_link >= shnum) || 789 (src_shdr.sh_link == 0)) 790 dst_shdr.sh_link = src_shdr.sh_link; 791 else if ((int)state->sec_table[src_shdr.sh_link].secno < 792 0) 793 dst_shdr.sh_link = 0; 794 else 795 dst_shdr.sh_link = 796 state->sec_table[src_shdr.sh_link].secno; 797 798 if ((src_shdr.sh_type == SHT_REL) || 799 (src_shdr.sh_type == SHT_RELA)) { 800 if ((src_shdr.sh_info >= shnum) || 801 ((int)state->sec_table[src_shdr. 802 sh_info].secno < 0)) 803 dst_shdr.sh_info = 0; 804 else 805 dst_shdr.sh_info = state-> 806 sec_table[src_shdr.sh_info].secno; 807 } 808 809 data = state->sec_table[scn_no].data; 810 if ((elf_data = elf_newdata(dst_scn)) == NULL) { 811 error_message(LIBELF_ERROR, 812 LIBelf_ERROR, elf_errmsg(-1), prog); 813 return (FAILURE); 814 } 815 *elf_data = *data; 816 817 /* 818 * SHT_{DYNSYM, SYMTAB} might need some change, as 819 * they may contain section symbols that reference 820 * removed sections. SHT_SUNW_LDYNSYM does not 821 * contain section symbols, and therefore does not 822 * have this issue. 823 */ 824 if (((src_shdr.sh_type == SHT_SYMTAB) || 825 (src_shdr.sh_type == SHT_DYNSYM)) && 826 src_shdr.sh_entsize != 0 && 827 (cmd_info->no_of_delete != 0 || 828 cmd_info->no_of_nulled != 0)) { 829 char *new_sym; 830 831 no_of_symbols = src_shdr.sh_size / 832 src_shdr.sh_entsize; 833 new_sym = malloc(no_of_symbols * 834 src_shdr.sh_entsize); 835 if (new_sym == NULL) { 836 error_message(MALLOC_ERROR, 837 PLAIN_ERROR, (char *)0, prog); 838 mcs_exit(FAILURE); 839 } 840 841 /* CSTYLED */ 842 elf_data->d_buf = (void *) new_sym; 843 for (c = 0; c < no_of_symbols; c++) { 844 GElf_Sym csym; 845 846 (void) gelf_getsym(data, c, &csym); 847 848 if ((csym.st_shndx < SHN_LORESERVE) && 849 (csym.st_shndx != SHN_UNDEF)) { 850 section_info_table *i; 851 i = &state-> 852 sec_table[csym.st_shndx]; 853 if (((int)i->secno != 854 DELETED) && 855 ((int)i->secno != NULLED)) { 856 csym.st_shndx = 857 i->secno; 858 } else { 859 /* BEGIN CSTYLED */ 860 if (src_shdr.sh_type == 861 SHT_SYMTAB) { 862 /* 863 * The section which 864 * this * symbol relates 865 * to is removed. 866 * There is no way to 867 * specify this fact, 868 * just change the shndx 869 * to 1. 870 */ 871 csym.st_shndx = 1; 872 } else { 873 /* 874 * If this is in a 875 * .dynsym, NULL it out. 876 */ 877 csym.st_shndx = 0; 878 csym.st_name = 0; 879 csym.st_value = 0; 880 csym.st_size = 0; 881 csym.st_info = 0; 882 csym.st_other = 0; 883 csym.st_shndx = 0; 884 } 885 /* END CSTYLED */ 886 } 887 } 888 889 (void) gelf_update_sym(elf_data, c, 890 &csym); 891 } 892 } 893 894 /* update SHT_SYMTAB_SHNDX */ 895 if ((src_shdr.sh_type == SHT_SYMTAB_SHNDX) && 896 (src_shdr.sh_entsize != 0) && 897 ((cmd_info->no_of_delete != 0) || 898 (cmd_info->no_of_nulled != 0))) { 899 GElf_Word *oldshndx; 900 GElf_Word *newshndx; 901 uint_t entcnt; 902 903 entcnt = src_shdr.sh_size / 904 src_shdr.sh_entsize; 905 oldshndx = data->d_buf; 906 newshndx = malloc(entcnt * src_shdr.sh_entsize); 907 if (newshndx == NULL) { 908 error_message(MALLOC_ERROR, 909 PLAIN_ERROR, (char *)0, prog); 910 mcs_exit(FAILURE); 911 } 912 elf_data->d_buf = (void *)newshndx; 913 for (c = 0; c < entcnt; c++) { 914 if (oldshndx[c] != SHN_UNDEF) { 915 section_info_table *i; 916 i = &state-> 917 sec_table[oldshndx[c]]; 918 if (((int)i->secno != 919 DELETED) && 920 ((int)i->secno != NULLED)) 921 newshndx[c] = i->secno; 922 else 923 newshndx[c] = 924 oldshndx[c]; 925 } else 926 newshndx[c] = 927 oldshndx[c]; 928 } 929 } 930 931 /* 932 * If the section is to be updated, 933 * do so. 934 */ 935 if (ISCANDIDATE(info->flags)) { 936 if ((GET_LOC(info->flags) == PRIOR) && 937 (((int)info->secno == NULLED) || 938 ((int)info->secno == EXPANDED) || 939 ((int)info->secno == SHRUNK))) { 940 /* 941 * The section is updated, 942 * but the position is not too 943 * good. Need to NULL this out. 944 */ 945 dst_shdr.sh_name = 0; 946 dst_shdr.sh_type = SHT_PROGBITS; 947 if ((int)info->secno != NULLED) { 948 (cmd_info->no_of_moved)++; 949 SET_MOVING(info->flags); 950 } 951 } else { 952 /* 953 * The section is positioned AFTER, 954 * or there are no segments. 955 * It is safe to update this section. 956 */ 957 data = state->sec_table[scn_no].mdata; 958 *elf_data = *data; 959 dst_shdr.sh_size = elf_data->d_size; 960 } 961 } 962 /* add new section name to shstrtab? */ 963 else if (!state->Sect_exists && 964 (state->new_sec_string != NULL) && 965 (scn_no == shstrndx) && 966 (dst_shdr.sh_type == SHT_STRTAB) && 967 ((src_ehdr->e_phnum == 0) || 968 ((x = scn_location(dst_scn, dst_elf, state)) 969 != IN) || 970 (x != PRIOR))) { 971 size_t sect_len; 972 973 sect_len = strlen(SECT_NAME); 974 if ((elf_data->d_buf = 975 malloc((dst_shdr.sh_size + 976 sect_len + 1))) == NULL) { 977 error_message(MALLOC_ERROR, 978 PLAIN_ERROR, (char *)0, prog); 979 mcs_exit(FAILURE); 980 } 981 /* put original data plus new data in section */ 982 (void) memcpy(elf_data->d_buf, 983 data->d_buf, data->d_size); 984 (void) memcpy(&((char *)elf_data->d_buf) 985 [data->d_size], SECT_NAME, sect_len + 1); 986 /* LINTED */ 987 new_sh_name = (int)dst_shdr.sh_size; 988 dst_shdr.sh_size += sect_len + 1; 989 elf_data->d_size += sect_len + 1; 990 } 991 992 /* 993 * Compute offsets. 994 */ 995 if (src_ehdr->e_phnum != 0) { 996 /* 997 * Compute section offset. 998 */ 999 if (state->off_table[scn_no] == 0) { 1000 if (dst_shdr.sh_addralign != 0) { 1001 r = new_offset % 1002 dst_shdr.sh_addralign; 1003 if (r) 1004 new_offset += 1005 dst_shdr. 1006 sh_addralign - r; 1007 } 1008 dst_shdr.sh_offset = new_offset; 1009 elf_data->d_off = 0; 1010 } else { 1011 if (state->nobits_table[scn_no] == 0) 1012 new_offset = 1013 state->off_table[scn_no]; 1014 } 1015 if (state->nobits_table[scn_no] == 0) 1016 new_offset += dst_shdr.sh_size; 1017 } 1018 1019 /* flush changes */ 1020 (void) gelf_update_shdr(dst_scn, &dst_shdr); 1021 } 1022 scn_no++; 1023 } 1024 1025 /* 1026 * This is the real new section. 1027 */ 1028 if (!state->Sect_exists && state->new_sec_string != NULL) { 1029 size_t string_size; 1030 string_size = strlen(state->new_sec_string) + 1; 1031 if ((dst_scn = elf_newscn(dst_elf)) == NULL) { 1032 error_message(LIBELF_ERROR, 1033 LIBelf_ERROR, elf_errmsg(-1), prog); 1034 return (FAILURE); 1035 } 1036 (void) gelf_getshdr(dst_scn, &dst_shdr); 1037 1038 dst_shdr.sh_name = new_sh_name; 1039 dst_shdr.sh_type = SHT_PROGBITS; 1040 dst_shdr.sh_flags = 0; 1041 dst_shdr.sh_addr = 0; 1042 if (src_ehdr->e_phnum != NULL) 1043 dst_shdr.sh_offset = new_offset; 1044 else 1045 dst_shdr.sh_offset = 0; 1046 dst_shdr.sh_size = string_size + 1; 1047 dst_shdr.sh_link = 0; 1048 dst_shdr.sh_info = 0; 1049 dst_shdr.sh_addralign = 1; 1050 dst_shdr.sh_entsize = 0; 1051 (void) gelf_update_shdr(dst_scn, &dst_shdr); /* flush changes */ 1052 1053 if ((elf_data = elf_newdata(dst_scn)) == NULL) { 1054 error_message(LIBELF_ERROR, 1055 LIBelf_ERROR, elf_errmsg(-1), prog); 1056 return (FAILURE); 1057 } 1058 elf_data->d_size = string_size + 1; 1059 if ((elf_data->d_buf = (char *) 1060 calloc(1, string_size + 1)) == NULL) { 1061 error_message(MALLOC_ERROR, 1062 PLAIN_ERROR, (char *)0, prog); 1063 mcs_exit(FAILURE); 1064 } 1065 (void) memcpy(&((char *)elf_data->d_buf)[1], 1066 state->new_sec_string, string_size); 1067 elf_data->d_align = 1; 1068 new_offset += string_size + 1; 1069 } 1070 1071 /* 1072 * If there are sections which needed to be moved, 1073 * then do it here. 1074 */ 1075 if (cmd_info->no_of_moved != 0) { 1076 int cnt; 1077 info = &state->sec_table[0]; 1078 1079 for (cnt = 0; cnt < shnum; cnt++, info++) { 1080 if ((GET_MOVING(info->flags)) == 0) 1081 continue; 1082 1083 if ((src_scn = elf_getscn(src_elf, info->osecno)) == 1084 NULL) { 1085 error_message(LIBELF_ERROR, 1086 LIBelf_ERROR, elf_errmsg(-1), prog); 1087 return (FAILURE); 1088 } 1089 if (gelf_getshdr(src_scn, &src_shdr) == NULL) { 1090 error_message(LIBELF_ERROR, 1091 LIBelf_ERROR, elf_errmsg(-1), prog); 1092 return (FAILURE); 1093 } 1094 if ((dst_scn = elf_newscn(dst_elf)) == NULL) { 1095 error_message(LIBELF_ERROR, 1096 LIBelf_ERROR, elf_errmsg(-1), prog); 1097 return (FAILURE); 1098 } 1099 if (gelf_getshdr(dst_scn, &dst_shdr) == NULL) { 1100 error_message(LIBELF_ERROR, 1101 LIBelf_ERROR, elf_errmsg(-1), prog); 1102 return (FAILURE); 1103 } 1104 dst_shdr = src_shdr; 1105 1106 data = info->mdata; 1107 1108 dst_shdr.sh_offset = new_offset; /* UPDATE fields */ 1109 dst_shdr.sh_size = data->d_size; 1110 1111 if ((shnum >= src_shdr.sh_link) || 1112 (src_shdr.sh_link == 0)) 1113 dst_shdr.sh_link = src_shdr.sh_link; 1114 else 1115 dst_shdr.sh_link = 1116 state->sec_table[src_shdr.sh_link].osecno; 1117 1118 if ((shnum >= src_shdr.sh_info) || 1119 (src_shdr.sh_info == 0)) 1120 dst_shdr.sh_info = src_shdr.sh_info; 1121 else 1122 dst_shdr.sh_info = 1123 state->sec_table[src_shdr.sh_info].osecno; 1124 (void) gelf_update_shdr(dst_scn, &dst_shdr); 1125 if ((elf_data = elf_newdata(dst_scn)) == NULL) { 1126 error_message(LIBELF_ERROR, 1127 LIBelf_ERROR, elf_errmsg(-1), prog); 1128 return (FAILURE); 1129 } 1130 (void) memcpy(elf_data, data, sizeof (Elf_Data)); 1131 1132 new_offset += data->d_size; 1133 } 1134 } 1135 1136 /* 1137 * In the event that the position of the sting table has changed, 1138 * as a result of deleted sections, update the ehdr->e_shstrndx. 1139 */ 1140 if ((shstrndx > 0) && (shnum > 0) && 1141 (state->sec_table[shstrndx].secno < shnum)) { 1142 if (state->sec_table[shstrndx].secno < SHN_LORESERVE) { 1143 dst_ehdr.e_shstrndx = 1144 state->sec_table[dst_ehdr.e_shstrndx].secno; 1145 } else { 1146 Elf_Scn *_scn; 1147 GElf_Shdr shdr0; 1148 1149 /* 1150 * If shstrndx requires 'Extended ELF Sections' 1151 * then it is stored in shdr[0].sh_link 1152 */ 1153 dst_ehdr.e_shstrndx = SHN_XINDEX; 1154 if ((_scn = elf_getscn(dst_elf, 0)) == NULL) { 1155 error_message(LIBELF_ERROR, 1156 LIBelf_ERROR, elf_errmsg(-1), prog); 1157 return (FAILURE); 1158 } 1159 (void) gelf_getshdr(_scn, &shdr0); 1160 shdr0.sh_link = state->sec_table[shstrndx].secno; 1161 (void) gelf_update_shdr(_scn, &shdr0); 1162 } 1163 } 1164 1165 if (src_ehdr->e_phnum != 0) { 1166 size_t align = gelf_fsize(dst_elf, ELF_T_ADDR, 1, EV_CURRENT); 1167 1168 /* UPDATE location of program header table */ 1169 if (location(dst_ehdr.e_phoff, 0, dst_elf, state) == AFTER) { 1170 r = new_offset % align; 1171 if (r) 1172 new_offset += align - r; 1173 1174 dst_ehdr.e_phoff = new_offset; 1175 new_offset += dst_ehdr.e_phnum * dst_ehdr.e_phentsize; 1176 } 1177 /* UPDATE location of section header table */ 1178 if ((location(dst_ehdr.e_shoff, 0, src_elf, state) == AFTER) || 1179 ((location(dst_ehdr.e_shoff, 0, src_elf, state) == PRIOR) && 1180 (!state->Sect_exists && state->new_sec_string != NULL))) { 1181 r = new_offset % align; 1182 if (r) 1183 new_offset += align - r; 1184 1185 dst_ehdr.e_shoff = new_offset; 1186 } 1187 1188 /* 1189 * The NOTE segment is the one segment whos 1190 * sections might get moved by mcs processing. 1191 * Make sure that the NOTE segments offset points 1192 * to the .note section. 1193 */ 1194 if ((state->notesegndx != -1) && (state->notesctndx != -1) && 1195 (state->sec_table[state->notesctndx].secno)) { 1196 Elf_Scn * notescn; 1197 GElf_Shdr nshdr; 1198 1199 notescn = elf_getscn(dst_elf, 1200 state->sec_table[state->notesctndx].secno); 1201 (void) gelf_getshdr(notescn, &nshdr); 1202 1203 if (gelf_getclass(dst_elf) == ELFCLASS32) { 1204 Elf32_Phdr * ph = elf32_getphdr(dst_elf) + 1205 state->notesegndx; 1206 /* LINTED */ 1207 ph->p_offset = (Elf32_Off)nshdr.sh_offset; 1208 } else { 1209 Elf64_Phdr * ph = elf64_getphdr(dst_elf) + 1210 state->notesegndx; 1211 ph->p_offset = (Elf64_Off)nshdr.sh_offset; 1212 } 1213 } 1214 } 1215 1216 /* copy ehdr changes back into real ehdr */ 1217 (void) gelf_update_ehdr(dst_elf, &dst_ehdr); 1218 if (elf_update(dst_elf, ELF_C_WRITE) < 0) { 1219 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 1220 return (FAILURE); 1221 } 1222 1223 (void) elf_end(dst_elf); 1224 (void) close(fdtmp); 1225 return (SUCCESS); 1226 } 1227 1228 /* 1229 * Search through PHT saving the beginning and ending segment offsets 1230 */ 1231 static int 1232 build_segment_table(Elf * elf, GElf_Ehdr * ehdr, file_state_t *state) 1233 { 1234 unsigned int i; 1235 1236 state->b_e_seg_table = (Seg_Table *) 1237 calloc(ehdr->e_phnum, sizeof (Seg_Table)); 1238 if (state->b_e_seg_table == NULL) { 1239 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 1240 mcs_exit(FAILURE); 1241 } 1242 1243 for (i = 0; i < ehdr->e_phnum; i++) { 1244 GElf_Phdr ph; 1245 1246 (void) gelf_getphdr(elf, i, &ph); 1247 1248 /* 1249 * remember the note SEGMENTS index so that we can 1250 * re-set it's p_offset later if needed. 1251 */ 1252 if (ph.p_type == PT_NOTE) 1253 state->notesegndx = i; 1254 1255 state->b_e_seg_table[i].p_offset = ph.p_offset; 1256 state->b_e_seg_table[i].p_memsz = ph.p_offset + ph.p_memsz; 1257 state->b_e_seg_table[i].p_filesz = ph.p_offset + ph.p_filesz; 1258 } 1259 return (SUCCESS); 1260 } 1261 1262 1263 static void 1264 copy_elf_file_to_temp_ar_file( 1265 int fdartmp, 1266 Elf_Arhdr *mem_header, 1267 char *cur_file) 1268 { 1269 char *buf; 1270 char mem_header_buf[sizeof (struct ar_hdr) + 1]; 1271 int fdtmp3; 1272 struct stat stbuf; 1273 1274 if ((fdtmp3 = open(elftmpfile, O_RDONLY)) == -1) { 1275 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno), 1276 prog, elftmpfile); 1277 mcs_exit(FAILURE); 1278 } 1279 1280 (void) stat(elftmpfile, &stbuf); /* for size of file */ 1281 1282 if ((buf = 1283 malloc(ROUNDUP(stbuf.st_size))) == NULL) { 1284 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 1285 mcs_exit(FAILURE); 1286 } 1287 1288 if (read(fdtmp3, buf, stbuf.st_size) != stbuf.st_size) { 1289 error_message(READ_MANI_ERROR, SYSTEM_ERROR, strerror(errno), 1290 prog, elftmpfile, cur_file); 1291 mcs_exit(FAILURE); 1292 } 1293 1294 (void) sprintf(mem_header_buf, FORMAT, mem_header->ar_rawname, 1295 mem_header->ar_date, (unsigned)mem_header->ar_uid, 1296 (unsigned)mem_header->ar_gid, (unsigned)mem_header->ar_mode, 1297 stbuf.st_size, ARFMAG); 1298 1299 if (write(fdartmp, mem_header_buf, 1300 (unsigned)sizeof (struct ar_hdr)) != 1301 (unsigned)sizeof (struct ar_hdr)) { 1302 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, strerror(errno), 1303 prog, elftmpfile, cur_file); 1304 mcs_exit(FAILURE); 1305 } 1306 1307 if (stbuf.st_size & 0x1) { 1308 buf[stbuf.st_size] = '\n'; 1309 if (write(fdartmp, buf, (size_t)ROUNDUP(stbuf.st_size)) != 1310 (size_t)ROUNDUP(stbuf.st_size)) { 1311 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, 1312 strerror(errno), prog, elftmpfile, cur_file); 1313 mcs_exit(FAILURE); 1314 } 1315 } else if (write(fdartmp, buf, stbuf.st_size) != stbuf.st_size) { 1316 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, 1317 strerror(errno), prog, elftmpfile, cur_file); 1318 mcs_exit(FAILURE); 1319 } 1320 free(buf); 1321 (void) close(fdtmp3); 1322 } 1323 1324 static void 1325 copy_non_elf_to_temp_ar( 1326 int fd, 1327 Elf *elf, 1328 int fdartmp, 1329 Elf_Arhdr *mem_header, 1330 char *cur_file, 1331 Cmd_Info *cmd_info) 1332 { 1333 char mem_header_buf[sizeof (struct ar_hdr) + 1]; 1334 char *file_buf; 1335 1336 if (strcmp(mem_header->ar_name, "/") != 0) { 1337 (void) sprintf(mem_header_buf, FORMAT, mem_header->ar_rawname, 1338 mem_header->ar_date, (unsigned)mem_header->ar_uid, 1339 (unsigned)mem_header->ar_gid, (unsigned)mem_header->ar_mode, 1340 mem_header->ar_size, ARFMAG); 1341 1342 if (write(fdartmp, mem_header_buf, sizeof (struct ar_hdr)) != 1343 sizeof (struct ar_hdr)) { 1344 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, 1345 strerror(errno), prog, cur_file); 1346 mcs_exit(FAILURE); 1347 } 1348 if ((file_buf = 1349 malloc(ROUNDUP(mem_header->ar_size))) == NULL) { 1350 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, 1351 prog); 1352 mcs_exit(FAILURE); 1353 } 1354 1355 if (lseek(fd, elf_getbase(elf), 0) != elf_getbase(elf)) { 1356 error_message(WRITE_MANI_ERROR, prog, cur_file); 1357 mcs_exit(FAILURE); 1358 } 1359 1360 if (read(fd, file_buf, 1361 (size_t)ROUNDUP(mem_header->ar_size)) != 1362 (size_t)ROUNDUP(mem_header->ar_size)) { 1363 error_message(READ_MANI_ERROR, SYSTEM_ERROR, 1364 strerror(errno), prog, cur_file); 1365 mcs_exit(FAILURE); 1366 } 1367 if (write(fdartmp, 1368 file_buf, 1369 (size_t)ROUNDUP(mem_header->ar_size)) != 1370 (size_t)ROUNDUP(mem_header->ar_size)) { 1371 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, 1372 strerror(errno), prog, cur_file); 1373 mcs_exit(FAILURE); 1374 } 1375 free(file_buf); 1376 } else if (CHK_OPT(cmd_info, MIGHT_CHG)) { 1377 error_message(SYM_TAB_AR_ERROR, PLAIN_ERROR, (char *)0, 1378 prog, cur_file); 1379 error_message(EXEC_AR_ERROR, PLAIN_ERROR, (char *)0, cur_file); 1380 } 1381 } 1382 1383 static void 1384 copy_file(int ofd, char *fname, char *temp_file_name) 1385 { 1386 enum { MMAP_USED, MMAP_UNUSED } mmap_status; 1387 int i; 1388 int fdtmp2; 1389 struct stat stbuf; 1390 char *buf; 1391 1392 for (i = 0; signum[i]; i++) /* started writing, cannot interrupt */ 1393 (void) signal(signum[i], SIG_IGN); 1394 1395 if ((fdtmp2 = open(temp_file_name, O_RDONLY)) == -1) { 1396 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno), 1397 prog, temp_file_name); 1398 mcs_exit(FAILURE); 1399 } 1400 1401 (void) stat(temp_file_name, &stbuf); /* for size of file */ 1402 1403 /* 1404 * Get the contents of the updated file. 1405 * First try mmap()'ing. If mmap() fails, 1406 * then use the malloc() and read(). 1407 */ 1408 mmap_status = MMAP_USED; 1409 buf = (char *)mmap(0, stbuf.st_size, PROT_READ, MAP_SHARED, fdtmp2, 0); 1410 if (buf == (caddr_t)-1) { 1411 if ((buf = 1412 malloc(stbuf.st_size * sizeof (char))) == NULL) { 1413 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, 1414 prog); 1415 mcs_exit(FAILURE); 1416 } 1417 1418 if (read(fdtmp2, buf, stbuf.st_size) != stbuf.st_size) { 1419 error_message(READ_SYS_ERROR, SYSTEM_ERROR, 1420 strerror(errno), prog, temp_file_name); 1421 mcs_exit(FAILURE); 1422 } 1423 mmap_status = MMAP_UNUSED; 1424 } 1425 1426 if (ftruncate(ofd, 0) == -1) { 1427 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno), 1428 prog, fname); 1429 mcs_exit(FAILURE); 1430 } 1431 if (lseek(ofd, 0, SEEK_SET) == -1) { 1432 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno), 1433 prog, fname); 1434 mcs_exit(FAILURE); 1435 } 1436 if ((write(ofd, buf, stbuf.st_size)) != stbuf.st_size) { 1437 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno), 1438 prog, fname); 1439 mcs_exit(FAILURE); 1440 } 1441 1442 /* 1443 * clean 1444 */ 1445 if (mmap_status == MMAP_USED) 1446 (void) munmap(buf, stbuf.st_size); 1447 else 1448 free(buf); 1449 (void) close(fdtmp2); 1450 (void) unlink(temp_file_name); /* temp file */ 1451 } 1452 1453 static uint64_t 1454 location(int64_t offset, int mem_search, Elf * elf, file_state_t *state) 1455 { 1456 int i; 1457 uint64_t upper; 1458 GElf_Ehdr ehdr; 1459 1460 (void) gelf_getehdr(elf, &ehdr); 1461 1462 for (i = 0; i < ehdr.e_phnum; i++) { 1463 if (mem_search) 1464 upper = state->b_e_seg_table[i].p_memsz; 1465 else 1466 upper = state->b_e_seg_table[i].p_filesz; 1467 if ((offset >= state->b_e_seg_table[i].p_offset) && 1468 (offset <= upper)) 1469 return (IN); 1470 else if (offset < state->b_e_seg_table[i].p_offset) 1471 return (PRIOR); 1472 } 1473 return (AFTER); 1474 } 1475 1476 static uint64_t 1477 scn_location(Elf_Scn * scn, Elf * elf, file_state_t *state) 1478 { 1479 GElf_Shdr shdr; 1480 1481 (void) gelf_getshdr(scn, &shdr); 1482 1483 /* 1484 * If the section is not a NOTE section and it has no 1485 * virtual address then it is not part of a mapped segment. 1486 */ 1487 if (shdr.sh_addr == 0) 1488 return (location(shdr.sh_offset + shdr.sh_size, 0, elf, state)); 1489 1490 return (location(shdr.sh_offset + shdr.sh_size, 1, elf, state)); 1491 } 1492 1493 static void 1494 initialize(int shnum, Cmd_Info *cmd_info, file_state_t *state) 1495 { 1496 /* 1497 * Initialize command info 1498 */ 1499 cmd_info->no_of_append = cmd_info->no_of_delete = 1500 cmd_info->no_of_nulled = cmd_info->no_of_compressed = 1501 cmd_info->no_of_moved = 0; 1502 cmd_info->sh_groups.head = cmd_info->sh_groups.tail = 0; 1503 1504 state->sec_table = (section_info_table *) 1505 calloc(shnum + 1, sizeof (section_info_table)); 1506 if (state->sec_table == NULL) { 1507 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 1508 exit(FAILURE); 1509 } 1510 1511 state->off_table = (int64_t *)calloc(shnum, sizeof (int64_t)); 1512 if (state->off_table == NULL) { 1513 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 1514 exit(FAILURE); 1515 } 1516 1517 state->nobits_table = (int64_t *)calloc(shnum, sizeof (int64_t)); 1518 if (state->nobits_table == NULL) { 1519 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 1520 exit(FAILURE); 1521 } 1522 } 1523 1524 /* 1525 * Update the contents of SHT_GROUP if needed 1526 */ 1527 static void 1528 post_process(Cmd_Info *cmd_info, file_state_t *state) 1529 { 1530 Listnode * lnp, *plnp; 1531 section_info_table * sinfo; 1532 Word * grpdata, *ngrpdata; 1533 int64_t sno, sno2; 1534 Word i, j, num; 1535 1536 /* 1537 * If no change is required, then return. 1538 */ 1539 if ((cmd_info->flags & (SHF_GROUP_MOVE|SHF_GROUP_DEL)) == 0) 1540 return; 1541 1542 /* 1543 * If SHF_GROUP sections were removed, we might need to 1544 * remove SHT_GROUP sections. 1545 */ 1546 if (cmd_info->flags & SHF_GROUP_DEL) { 1547 Word grpcnt; 1548 int deleted = 0; 1549 1550 for (LIST_TRAVERSE(&cmd_info->sh_groups, lnp, sinfo)) { 1551 if (sinfo->secno == (GElf_Word)DELETED) 1552 continue; 1553 num = (sinfo->shdr).sh_size/sizeof (Word); 1554 grpcnt = 0; 1555 grpdata = (Word *)(sinfo->data->d_buf); 1556 for (i = 1; i < num; i++) { 1557 if (state->sec_table[grpdata[i]].secno != 1558 (GElf_Word)DELETED) 1559 grpcnt++; 1560 } 1561 1562 /* 1563 * All members in this SHT_GROUP were removed. 1564 * We can remove this SHT_GROUP. 1565 */ 1566 if (grpcnt == 0) { 1567 sinfo->secno = (GElf_Word)DELETED; 1568 (cmd_info->no_of_delete)++; 1569 deleted = 1; 1570 } 1571 } 1572 1573 /* 1574 * If we deleted a SHT_GROUP section, 1575 * we need to reasign section numbers. 1576 */ 1577 if (deleted) { 1578 section_info_table *sinfo; 1579 1580 sno = 1; 1581 sno2 = 1; 1582 while (state->sec_table[sno].scn != (Elf_Scn *)-1) { 1583 sinfo = &state->sec_table[sno]; 1584 if (sinfo->secno != (GElf_Word) DELETED) 1585 sinfo->secno = sno2++; 1586 sno++; 1587 } 1588 } 1589 } 1590 1591 /* 1592 * Now we can update data buffers of the 1593 * SHT_GROUP sections. 1594 */ 1595 plnp = 0; 1596 for (LIST_TRAVERSE(&cmd_info->sh_groups, lnp, sinfo)) { 1597 if (plnp) 1598 free(plnp); 1599 plnp = lnp; 1600 if (sinfo->secno == (GElf_Word)DELETED) 1601 continue; 1602 num = (sinfo->shdr).sh_size/sizeof (Word); 1603 1604 /* 1605 * Need to generate the updated data buffer 1606 */ 1607 if ((sinfo->mdata = malloc(sizeof (Elf_Data))) == NULL) { 1608 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, 1609 prog); 1610 exit(FAILURE); 1611 } 1612 *(sinfo->mdata) = *(sinfo->data); 1613 if ((ngrpdata = sinfo->mdata->d_buf = 1614 malloc(sinfo->data->d_size)) == NULL) { 1615 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, 1616 prog); 1617 exit(FAILURE); 1618 } 1619 1620 grpdata = (Word *)(sinfo->data->d_buf); 1621 ngrpdata[0] = grpdata[0]; 1622 j = 1; 1623 for (i = 1; i < num; i++) { 1624 if (state->sec_table[grpdata[i]].secno != 1625 (GElf_Word)DELETED) { 1626 ngrpdata[j++] = 1627 state->sec_table[grpdata[i]].secno; 1628 } 1629 } 1630 sinfo->mdata->d_size = j * sizeof (Word); 1631 sinfo->data = sinfo->mdata; 1632 } 1633 if (plnp) 1634 free(plnp); 1635 } 1636