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