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