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 2006 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 /* SHT_{DYNSYM, SYMTAB} might need some change */ 790 if (((src_shdr.sh_type == SHT_SYMTAB) || 791 (src_shdr.sh_type == SHT_DYNSYM)) && 792 src_shdr.sh_entsize != 0 && 793 (cmd_info->no_of_delete != 0 || 794 cmd_info->no_of_nulled != 0)) { 795 char *new_sym; 796 797 no_of_symbols = src_shdr.sh_size / 798 src_shdr.sh_entsize; 799 new_sym = malloc(no_of_symbols * 800 src_shdr.sh_entsize); 801 if (new_sym == NULL) { 802 error_message(MALLOC_ERROR, 803 PLAIN_ERROR, (char *)0, prog); 804 mcs_exit(FAILURE); 805 } 806 807 /* CSTYLED */ 808 elf_data->d_buf = (void *) new_sym; 809 for (c = 0; c < no_of_symbols; c++) { 810 GElf_Sym csym; 811 812 (void) gelf_getsym(data, c, &csym); 813 814 if ((csym.st_shndx < SHN_LORESERVE) && 815 (csym.st_shndx != SHN_UNDEF)) { 816 section_info_table *i; 817 i = &sec_table[csym.st_shndx]; 818 if (((int)i->secno != 819 DELETED) && 820 ((int)i->secno != NULLED)) 821 csym.st_shndx = 822 i->secno; 823 else { 824 if (src_shdr.sh_type == 825 SHT_SYMTAB) 826 /* 827 * The section which 828 * this * symbol relates 829 * to is removed. 830 * There is no way to 831 * specify this fact, 832 * just change the shndx 833 * to 1. 834 */ 835 csym.st_shndx = 1; 836 else { 837 /* 838 * If this is in a 839 * .dynsym, NULL it out. 840 */ 841 csym.st_shndx = 0; 842 csym.st_name = 0; 843 csym.st_value = 0; 844 csym.st_size = 0; 845 csym.st_info = 0; 846 csym.st_other = 0; 847 csym.st_shndx = 0; 848 } 849 } 850 } 851 852 (void) gelf_update_sym(elf_data, c, 853 &csym); 854 } 855 } 856 857 /* update SHT_SYMTAB_SHNDX */ 858 if ((src_shdr.sh_type == SHT_SYMTAB_SHNDX) && 859 (src_shdr.sh_entsize != 0) && 860 ((cmd_info->no_of_delete != 0) || 861 (cmd_info->no_of_nulled != 0))) { 862 GElf_Word *oldshndx; 863 GElf_Word *newshndx; 864 uint_t entcnt; 865 866 entcnt = src_shdr.sh_size / 867 src_shdr.sh_entsize; 868 oldshndx = data->d_buf; 869 newshndx = malloc(entcnt * 870 src_shdr.sh_entsize); 871 if (newshndx == NULL) { 872 error_message(MALLOC_ERROR, 873 PLAIN_ERROR, (char *)0, prog); 874 mcs_exit(FAILURE); 875 } 876 elf_data->d_buf = (void *)newshndx; 877 for (c = 0; c < entcnt; c++) { 878 if (oldshndx[c] != SHN_UNDEF) { 879 section_info_table *i; 880 i = &sec_table[oldshndx[c]]; 881 if (((int)i->secno != 882 DELETED) && 883 ((int)i->secno != NULLED)) 884 newshndx[c] = i->secno; 885 else 886 newshndx[c] = 887 oldshndx[c]; 888 } else 889 newshndx[c] = 890 oldshndx[c]; 891 } 892 } 893 894 /* 895 * If the section is to be updated, 896 * do so. 897 */ 898 if (ISCANDIDATE(info->flags)) { 899 if ((GET_LOC(info->flags) == PRIOR) && 900 (((int)info->secno == NULLED) || 901 ((int)info->secno == EXPANDED) || 902 ((int)info->secno == SHRUNK))) { 903 /* 904 * The section is updated, 905 * but the position is not too 906 * good. Need to NULL this out. 907 */ 908 dst_shdr.sh_name = 0; 909 dst_shdr.sh_type = SHT_PROGBITS; 910 if ((int)info->secno != NULLED) { 911 (cmd_info->no_of_moved)++; 912 SET_MOVING(info->flags); 913 } 914 } else { 915 /* 916 * The section is positioned AFTER, 917 * or there are no segments. 918 * It is safe to update this section. 919 */ 920 data = sec_table[scn_no].mdata; 921 *elf_data = *data; 922 dst_shdr.sh_size = elf_data->d_size; 923 } 924 } 925 /* add new section name to shstrtab? */ 926 else if (!Sect_exists && 927 (new_sec_string != NULL) && 928 (scn_no == shstrndx) && 929 (dst_shdr.sh_type == SHT_STRTAB) && 930 ((src_ehdr->e_phnum == 0) || 931 ((x = scn_location(dst_scn, dst_elf)) != IN) || 932 (x != PRIOR))) { 933 size_t sect_len; 934 935 sect_len = strlen(SECT_NAME); 936 if ((elf_data->d_buf = 937 malloc((dst_shdr.sh_size + 938 sect_len + 1))) == NULL) { 939 error_message(MALLOC_ERROR, 940 PLAIN_ERROR, (char *)0, prog); 941 mcs_exit(FAILURE); 942 } 943 /* put original data plus new data in section */ 944 (void) memcpy(elf_data->d_buf, 945 data->d_buf, data->d_size); 946 (void) memcpy(&((char *)elf_data->d_buf) 947 [data->d_size], 948 SECT_NAME, 949 sect_len + 1); 950 /* LINTED */ 951 new_sh_name = (int)dst_shdr.sh_size; 952 dst_shdr.sh_size += sect_len + 1; 953 elf_data->d_size += sect_len + 1; 954 } 955 956 /* 957 * Compute offsets. 958 */ 959 if (src_ehdr->e_phnum != 0) { 960 /* 961 * Compute section offset. 962 */ 963 if (off_table[scn_no] == 0) { 964 if (dst_shdr.sh_addralign != 0) { 965 r = new_offset % 966 dst_shdr.sh_addralign; 967 if (r) 968 new_offset += 969 dst_shdr.sh_addralign - r; 970 } 971 dst_shdr.sh_offset = new_offset; 972 elf_data->d_off = 0; 973 } else { 974 if (nobits_table[scn_no] == 0) 975 new_offset = off_table[scn_no]; 976 } 977 if (nobits_table[scn_no] == 0) 978 new_offset += dst_shdr.sh_size; 979 } 980 } 981 982 (void) gelf_update_shdr(dst_scn, &dst_shdr); /* flush changes */ 983 scn_no++; 984 } 985 986 /* 987 * This is the real new section. 988 */ 989 if (!Sect_exists && new_sec_string != NULL) { 990 size_t string_size; 991 string_size = strlen(new_sec_string) + 1; 992 if ((dst_scn = elf_newscn(dst_elf)) == NULL) { 993 error_message(LIBELF_ERROR, 994 LIBelf_ERROR, elf_errmsg(-1), prog); 995 return (FAILURE); 996 } 997 (void) gelf_getshdr(dst_scn, &dst_shdr); 998 999 dst_shdr.sh_name = new_sh_name; 1000 dst_shdr.sh_type = SHT_PROGBITS; 1001 dst_shdr.sh_flags = 0; 1002 dst_shdr.sh_addr = 0; 1003 if (src_ehdr->e_phnum != NULL) 1004 dst_shdr.sh_offset = new_offset; 1005 else 1006 dst_shdr.sh_offset = 0; 1007 dst_shdr.sh_size = string_size + 1; 1008 dst_shdr.sh_link = 0; 1009 dst_shdr.sh_info = 0; 1010 dst_shdr.sh_addralign = 1; 1011 dst_shdr.sh_entsize = 0; 1012 (void) gelf_update_shdr(dst_scn, &dst_shdr); /* flush changes */ 1013 1014 if ((elf_data = elf_newdata(dst_scn)) == NULL) { 1015 error_message(LIBELF_ERROR, 1016 LIBelf_ERROR, elf_errmsg(-1), prog); 1017 return (FAILURE); 1018 } 1019 elf_data->d_size = string_size + 1; 1020 if ((elf_data->d_buf = (char *) 1021 calloc(1, string_size + 1)) == NULL) { 1022 error_message(MALLOC_ERROR, 1023 PLAIN_ERROR, (char *)0, 1024 prog); 1025 mcs_exit(FAILURE); 1026 } 1027 (void) memcpy(&((char *)elf_data->d_buf)[1], 1028 new_sec_string, string_size); 1029 elf_data->d_align = 1; 1030 new_offset += string_size + 1; 1031 } 1032 1033 /* 1034 * If there are sections which needed to be moved, 1035 * then do it here. 1036 */ 1037 if (cmd_info->no_of_moved != 0) { 1038 int cnt; 1039 info = &sec_table[0]; 1040 1041 for (cnt = 0; cnt < shnum; cnt++, info++) { 1042 if ((GET_MOVING(info->flags)) == 0) 1043 continue; 1044 1045 if ((src_scn = elf_getscn(src_elf, info->osecno)) == 1046 NULL) { 1047 error_message(LIBELF_ERROR, 1048 LIBelf_ERROR, elf_errmsg(-1), prog); 1049 return (FAILURE); 1050 } 1051 if (gelf_getshdr(src_scn, &src_shdr) == NULL) { 1052 error_message(LIBELF_ERROR, 1053 LIBelf_ERROR, elf_errmsg(-1), prog); 1054 return (FAILURE); 1055 } 1056 if ((dst_scn = elf_newscn(dst_elf)) == NULL) { 1057 error_message(LIBELF_ERROR, 1058 LIBelf_ERROR, elf_errmsg(-1), prog); 1059 return (FAILURE); 1060 } 1061 if (gelf_getshdr(dst_scn, &dst_shdr) == NULL) { 1062 error_message(LIBELF_ERROR, 1063 LIBelf_ERROR, elf_errmsg(-1), prog); 1064 return (FAILURE); 1065 } 1066 dst_shdr = src_shdr; 1067 1068 data = info->mdata; 1069 1070 dst_shdr.sh_offset = new_offset; /* UPDATE fields */ 1071 dst_shdr.sh_size = data->d_size; 1072 1073 if ((shnum >= src_shdr.sh_link) || 1074 (src_shdr.sh_link == 0)) 1075 dst_shdr.sh_link = src_shdr.sh_link; 1076 else 1077 dst_shdr.sh_link = 1078 sec_table[src_shdr.sh_link].osecno; 1079 1080 if ((shnum >= src_shdr.sh_info) || 1081 (src_shdr.sh_info == 0)) 1082 dst_shdr.sh_info = src_shdr.sh_info; 1083 else 1084 dst_shdr.sh_info = 1085 sec_table[src_shdr.sh_info].osecno; 1086 (void) gelf_update_shdr(dst_scn, &dst_shdr); 1087 if ((elf_data = elf_newdata(dst_scn)) == NULL) { 1088 error_message(LIBELF_ERROR, 1089 LIBelf_ERROR, elf_errmsg(-1), prog); 1090 return (FAILURE); 1091 } 1092 (void) memcpy(elf_data, data, sizeof (Elf_Data)); 1093 1094 new_offset += data->d_size; 1095 } 1096 } 1097 1098 /* 1099 * In the event that the position of the sting table has changed, 1100 * as a result of deleted sections, update the ehdr->e_shstrndx. 1101 */ 1102 if (shstrndx > 0 && shnum > 0 && 1103 (sec_table[shstrndx].secno < shnum)) { 1104 if (sec_table[shstrndx].secno < SHN_LORESERVE) { 1105 dst_ehdr.e_shstrndx = 1106 sec_table[dst_ehdr.e_shstrndx].secno; 1107 } else { 1108 Elf_Scn *_scn; 1109 GElf_Shdr shdr0; 1110 /* 1111 * If shstrndx requires 'Extended ELF Sections' 1112 * then it is stored in shdr[0].sh_link 1113 */ 1114 dst_ehdr.e_shstrndx = SHN_XINDEX; 1115 if ((_scn = elf_getscn(dst_elf, 0)) == NULL) { 1116 error_message(LIBELF_ERROR, 1117 LIBelf_ERROR, elf_errmsg(-1), prog); 1118 return (FAILURE); 1119 } 1120 (void) gelf_getshdr(_scn, &shdr0); 1121 shdr0.sh_link = sec_table[shstrndx].secno; 1122 (void) gelf_update_shdr(_scn, &shdr0); 1123 } 1124 1125 } 1126 1127 1128 if (src_ehdr->e_phnum != 0) { 1129 size_t align = gelf_fsize(dst_elf, ELF_T_ADDR, 1, EV_CURRENT); 1130 1131 /* UPDATE location of program header table */ 1132 if (location(dst_ehdr.e_phoff, 0, dst_elf) == AFTER) { 1133 r = new_offset % align; 1134 if (r) 1135 new_offset += align - r; 1136 1137 dst_ehdr.e_phoff = new_offset; 1138 new_offset += dst_ehdr.e_phnum 1139 * dst_ehdr.e_phentsize; 1140 } 1141 /* UPDATE location of section header table */ 1142 if ((location(dst_ehdr.e_shoff, 0, src_elf) == AFTER) || 1143 ((location(dst_ehdr.e_shoff, 0, src_elf) == PRIOR) && 1144 (!Sect_exists && new_sec_string != NULL))) { 1145 r = new_offset % align; 1146 if (r) 1147 new_offset += align - r; 1148 1149 dst_ehdr.e_shoff = new_offset; 1150 } 1151 free(b_e_seg_table); 1152 1153 /* 1154 * The NOTE segment is the one segment whos 1155 * sections might get moved by mcs processing. 1156 * Make sure that the NOTE segments offset points 1157 * to the .note section. 1158 */ 1159 if ((notesegndx != -1) && (notesctndx != -1) && 1160 (sec_table[notesctndx].secno)) { 1161 Elf_Scn * notescn; 1162 GElf_Shdr nshdr; 1163 1164 notescn = elf_getscn(dst_elf, 1165 sec_table[notesctndx].secno); 1166 (void) gelf_getshdr(notescn, &nshdr); 1167 1168 if (gelf_getclass(dst_elf) == ELFCLASS32) { 1169 Elf32_Phdr * ph = elf32_getphdr(dst_elf) + 1170 notesegndx; 1171 /* LINTED */ 1172 ph->p_offset = (Elf32_Off)nshdr.sh_offset; 1173 } else { 1174 Elf64_Phdr * ph = elf64_getphdr(dst_elf) + 1175 notesegndx; 1176 ph->p_offset = (Elf64_Off)nshdr.sh_offset; 1177 } 1178 } 1179 } 1180 1181 /* copy ehdr changes back into real ehdr */ 1182 (void) gelf_update_ehdr(dst_elf, &dst_ehdr); 1183 if (elf_update(dst_elf, ELF_C_WRITE) < 0) { 1184 error_message(LIBELF_ERROR, 1185 LIBelf_ERROR, elf_errmsg(-1), prog); 1186 return (FAILURE); 1187 } 1188 1189 (void) elf_end(dst_elf); 1190 (void) close(fdtmp); 1191 return (SUCCESS); 1192 } 1193 1194 /* 1195 * Search through PHT saving the beginning and ending segment offsets 1196 */ 1197 static int 1198 build_segment_table(Elf * elf, GElf_Ehdr * ehdr) 1199 { 1200 unsigned int i; 1201 1202 if ((b_e_seg_table = (Seg_Table *) 1203 calloc(ehdr->e_phnum, sizeof (Seg_Table))) == NULL) { 1204 error_message(MALLOC_ERROR, 1205 PLAIN_ERROR, (char *)0, 1206 prog); 1207 mcs_exit(FAILURE); 1208 } 1209 1210 for (i = 0; i < ehdr->e_phnum; i++) { 1211 GElf_Phdr ph; 1212 1213 (void) gelf_getphdr(elf, i, &ph); 1214 1215 /* 1216 * remember the note SEGMENTS index so that we can 1217 * re-set it's p_offset later if needed. 1218 */ 1219 if (ph.p_type == PT_NOTE) 1220 notesegndx = i; 1221 1222 b_e_seg_table[i].p_offset = ph.p_offset; 1223 b_e_seg_table[i].p_memsz = ph.p_offset + ph.p_memsz; 1224 b_e_seg_table[i].p_filesz = ph.p_offset + ph.p_filesz; 1225 } 1226 return (SUCCESS); 1227 } 1228 1229 1230 static void 1231 copy_elf_file_to_temp_ar_file( 1232 int fdartmp, 1233 Elf_Arhdr *mem_header, 1234 char *cur_file) 1235 { 1236 char *buf; 1237 char mem_header_buf[sizeof (struct ar_hdr) + 1]; 1238 int fdtmp3; 1239 struct stat stbuf; 1240 1241 if ((fdtmp3 = open(elftmpfile, O_RDONLY)) == -1) { 1242 error_message(OPEN_TEMP_ERROR, 1243 SYSTEM_ERROR, strerror(errno), 1244 prog, elftmpfile); 1245 mcs_exit(FAILURE); 1246 } 1247 1248 (void) stat(elftmpfile, &stbuf); /* for size of file */ 1249 1250 if ((buf = 1251 malloc(ROUNDUP(stbuf.st_size))) == NULL) { 1252 error_message(MALLOC_ERROR, 1253 PLAIN_ERROR, (char *)0, 1254 prog); 1255 mcs_exit(FAILURE); 1256 } 1257 1258 if (read(fdtmp3, buf, stbuf.st_size) != stbuf.st_size) { 1259 error_message(READ_MANI_ERROR, 1260 SYSTEM_ERROR, strerror(errno), 1261 prog, elftmpfile, cur_file); 1262 mcs_exit(FAILURE); 1263 } 1264 1265 (void) sprintf(mem_header_buf, FORMAT, 1266 mem_header->ar_rawname, 1267 mem_header->ar_date, 1268 (unsigned)mem_header->ar_uid, 1269 (unsigned)mem_header->ar_gid, 1270 (unsigned)mem_header->ar_mode, 1271 stbuf.st_size, ARFMAG); 1272 1273 if (write(fdartmp, mem_header_buf, 1274 (unsigned)sizeof (struct ar_hdr)) != 1275 (unsigned)sizeof (struct ar_hdr)) { 1276 error_message(WRITE_MANI_ERROR, 1277 SYSTEM_ERROR, strerror(errno), 1278 prog, elftmpfile, cur_file); 1279 mcs_exit(FAILURE); 1280 } 1281 1282 if (stbuf.st_size & 0x1) { 1283 buf[stbuf.st_size] = '\n'; 1284 if (write(fdartmp, buf, (size_t)ROUNDUP(stbuf.st_size)) != 1285 (size_t)ROUNDUP(stbuf.st_size)) { 1286 error_message(WRITE_MANI_ERROR, 1287 SYSTEM_ERROR, strerror(errno), 1288 prog, elftmpfile, cur_file); 1289 mcs_exit(FAILURE); 1290 } 1291 } else if (write(fdartmp, buf, stbuf.st_size) != stbuf.st_size) { 1292 error_message(WRITE_MANI_ERROR, 1293 SYSTEM_ERROR, strerror(errno), 1294 prog, elftmpfile, cur_file); 1295 mcs_exit(FAILURE); 1296 } 1297 free(buf); 1298 (void) close(fdtmp3); 1299 } 1300 1301 static void 1302 copy_non_elf_to_temp_ar( 1303 int fd, 1304 Elf *elf, 1305 int fdartmp, 1306 Elf_Arhdr *mem_header, 1307 char *cur_file, 1308 Cmd_Info *cmd_info) 1309 { 1310 char mem_header_buf[sizeof (struct ar_hdr) + 1]; 1311 char *file_buf; 1312 1313 if (strcmp(mem_header->ar_name, "/") != 0) { 1314 (void) sprintf(mem_header_buf, FORMAT, 1315 mem_header->ar_rawname, 1316 mem_header->ar_date, 1317 (unsigned)mem_header->ar_uid, 1318 (unsigned)mem_header->ar_gid, 1319 (unsigned)mem_header->ar_mode, 1320 mem_header->ar_size, ARFMAG); 1321 1322 if (write(fdartmp, mem_header_buf, sizeof (struct ar_hdr)) != 1323 sizeof (struct ar_hdr)) { 1324 error_message(WRITE_MANI_ERROR, 1325 SYSTEM_ERROR, strerror(errno), 1326 prog, cur_file); 1327 mcs_exit(FAILURE); 1328 } 1329 if ((file_buf = 1330 malloc(ROUNDUP(mem_header->ar_size))) == NULL) { 1331 error_message(MALLOC_ERROR, 1332 PLAIN_ERROR, (char *)0, 1333 prog); 1334 mcs_exit(FAILURE); 1335 } 1336 1337 if (lseek(fd, elf_getbase(elf), 0) != elf_getbase(elf)) { 1338 error_message(WRITE_MANI_ERROR, 1339 prog, cur_file); 1340 mcs_exit(FAILURE); 1341 } 1342 1343 if (read(fd, file_buf, 1344 (size_t)ROUNDUP(mem_header->ar_size)) != 1345 (size_t)ROUNDUP(mem_header->ar_size)) { 1346 error_message(READ_MANI_ERROR, 1347 SYSTEM_ERROR, strerror(errno), 1348 prog, cur_file); 1349 mcs_exit(FAILURE); 1350 } 1351 if (write(fdartmp, 1352 file_buf, 1353 (size_t)ROUNDUP(mem_header->ar_size)) != 1354 (size_t)ROUNDUP(mem_header->ar_size)) { 1355 error_message(WRITE_MANI_ERROR, 1356 SYSTEM_ERROR, strerror(errno), 1357 prog, cur_file); 1358 mcs_exit(FAILURE); 1359 } 1360 free(file_buf); 1361 } else if (CHK_OPT(cmd_info, MIGHT_CHG)) { 1362 error_message(SYM_TAB_AR_ERROR, 1363 PLAIN_ERROR, (char *)0, 1364 prog, cur_file); 1365 error_message(EXEC_AR_ERROR, 1366 PLAIN_ERROR, (char *)0, 1367 cur_file); 1368 } 1369 } 1370 1371 static void 1372 copy_file(int ofd, char *fname, char *temp_file_name) 1373 { 1374 int i; 1375 int fdtmp2; 1376 struct stat stbuf; 1377 char *buf; 1378 1379 for (i = 0; signum[i]; i++) /* started writing, cannot interrupt */ 1380 (void) signal(signum[i], SIG_IGN); 1381 1382 if ((fdtmp2 = open(temp_file_name, O_RDONLY)) == -1) { 1383 error_message(OPEN_TEMP_ERROR, 1384 SYSTEM_ERROR, strerror(errno), 1385 prog, temp_file_name); 1386 mcs_exit(FAILURE); 1387 } 1388 1389 (void) stat(temp_file_name, &stbuf); /* for size of file */ 1390 1391 /* 1392 * Get the contents of the updated file. 1393 * First try mmap()'ing. If mmap() fails, 1394 * then use the malloc() and read(). 1395 */ 1396 i = MMAP_USED; 1397 if ((buf = (char *)mmap(0, stbuf.st_size, 1398 PROT_READ, MAP_SHARED, fdtmp2, 0)) == (caddr_t)-1) { 1399 if ((buf = 1400 malloc(stbuf.st_size * sizeof (char))) == NULL) { 1401 error_message(MALLOC_ERROR, 1402 PLAIN_ERROR, (char *)0, 1403 prog); 1404 mcs_exit(FAILURE); 1405 } 1406 1407 if (read(fdtmp2, buf, stbuf.st_size) != stbuf.st_size) { 1408 error_message(READ_SYS_ERROR, 1409 SYSTEM_ERROR, strerror(errno), 1410 prog, temp_file_name); 1411 mcs_exit(FAILURE); 1412 } 1413 i = MMAP_UNUSED; 1414 } 1415 1416 if (ftruncate(ofd, 0) == -1) { 1417 error_message(WRITE_MANI_ERROR2, 1418 SYSTEM_ERROR, strerror(errno), 1419 prog, fname); 1420 mcs_exit(FAILURE); 1421 } 1422 if (lseek(ofd, 0, SEEK_SET) == -1) { 1423 error_message(WRITE_MANI_ERROR2, 1424 SYSTEM_ERROR, strerror(errno), 1425 prog, fname); 1426 mcs_exit(FAILURE); 1427 } 1428 if ((write(ofd, buf, stbuf.st_size)) != stbuf.st_size) { 1429 error_message(WRITE_MANI_ERROR2, 1430 SYSTEM_ERROR, strerror(errno), 1431 prog, fname); 1432 mcs_exit(FAILURE); 1433 } 1434 1435 /* 1436 * clean 1437 */ 1438 if (i == MMAP_USED) 1439 (void) munmap(buf, stbuf.st_size); 1440 else 1441 free(buf); 1442 (void) close(fdtmp2); 1443 (void) unlink(temp_file_name); /* temp file */ 1444 } 1445 1446 static uint64_t 1447 location(int64_t offset, int mem_search, Elf * elf) 1448 { 1449 int i; 1450 uint64_t upper; 1451 GElf_Ehdr ehdr; 1452 1453 (void) gelf_getehdr(elf, &ehdr); 1454 1455 for (i = 0; i < ehdr.e_phnum; i++) { 1456 if (mem_search) 1457 upper = b_e_seg_table[i].p_memsz; 1458 else 1459 upper = b_e_seg_table[i].p_filesz; 1460 if ((offset >= b_e_seg_table[i].p_offset) && 1461 (offset <= upper)) 1462 return (IN); 1463 else if (offset < b_e_seg_table[i].p_offset) 1464 return (PRIOR); 1465 } 1466 return (AFTER); 1467 } 1468 1469 static uint64_t 1470 scn_location(Elf_Scn * scn, Elf * elf) 1471 { 1472 GElf_Shdr shdr; 1473 1474 (void) gelf_getshdr(scn, &shdr); 1475 1476 /* 1477 * If the section is not a NOTE section and it has no 1478 * virtual address then it is not part of a mapped segment. 1479 */ 1480 if (shdr.sh_addr == 0) 1481 return (location(shdr.sh_offset + shdr.sh_size, 0, elf)); 1482 1483 return (location(shdr.sh_offset + shdr.sh_size, 1, elf)); 1484 } 1485 1486 static void 1487 initialize(int shnum, Cmd_Info *cmd_info) 1488 { 1489 /* 1490 * Initialize command info 1491 */ 1492 cmd_info->no_of_append = cmd_info->no_of_delete = 1493 cmd_info->no_of_nulled = cmd_info->no_of_compressed = 1494 cmd_info->no_of_moved = 0; 1495 cmd_info->sh_groups.head = cmd_info->sh_groups.tail = 0; 1496 1497 if ((sec_table = (section_info_table *) 1498 calloc(shnum + 1, 1499 sizeof (section_info_table))) == NULL) { 1500 error_message(MALLOC_ERROR, 1501 PLAIN_ERROR, (char *)0, 1502 prog); 1503 exit(FAILURE); 1504 } 1505 1506 if ((off_table = (int64_t *) 1507 calloc(shnum, 1508 sizeof (int64_t))) == NULL) { 1509 error_message(MALLOC_ERROR, 1510 PLAIN_ERROR, (char *)0, 1511 prog); 1512 exit(FAILURE); 1513 } 1514 1515 if ((nobits_table = (int64_t *) 1516 calloc(shnum, sizeof (int64_t))) == NULL) { 1517 error_message(MALLOC_ERROR, 1518 PLAIN_ERROR, (char *)0, 1519 prog); 1520 exit(FAILURE); 1521 } 1522 } 1523 1524 /* 1525 * Update the contents of SHT_GROUP if needed 1526 */ 1527 void 1528 post_process(Cmd_Info *cmd_info) 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 (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 (sec_table[sno].scn != (Elf_Scn *)-1) { 1583 sinfo = &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, 1609 PLAIN_ERROR, (char *)0, 1610 prog); 1611 exit(FAILURE); 1612 } 1613 *(sinfo->mdata) = *(sinfo->data); 1614 if ((ngrpdata = sinfo->mdata->d_buf = 1615 malloc(sinfo->data->d_size)) == NULL) { 1616 error_message(MALLOC_ERROR, 1617 PLAIN_ERROR, (char *)0, 1618 prog); 1619 exit(FAILURE); 1620 } 1621 1622 grpdata = (Word *)(sinfo->data->d_buf); 1623 ngrpdata[0] = grpdata[0]; 1624 j = 1; 1625 for (i = 1; i < num; i++) { 1626 if (sec_table[grpdata[i]].secno != (GElf_Word)DELETED) { 1627 ngrpdata[j++] = 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