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