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 /* 1112 * If shstrndx requires 'Extended ELF Sections' 1113 * then it is stored in shdr[0].sh_link 1114 */ 1115 dst_ehdr.e_shstrndx = SHN_XINDEX; 1116 if ((_scn = elf_getscn(dst_elf, 0)) == NULL) { 1117 error_message(LIBELF_ERROR, 1118 LIBelf_ERROR, elf_errmsg(-1), prog); 1119 return (FAILURE); 1120 } 1121 (void) gelf_getshdr(_scn, &shdr0); 1122 shdr0.sh_link = sec_table[shstrndx].secno; 1123 (void) gelf_update_shdr(_scn, &shdr0); 1124 } 1125 } 1126 1127 if (src_ehdr->e_phnum != 0) { 1128 size_t align = gelf_fsize(dst_elf, ELF_T_ADDR, 1, EV_CURRENT); 1129 1130 /* UPDATE location of program header table */ 1131 if (location(dst_ehdr.e_phoff, 0, dst_elf) == AFTER) { 1132 r = new_offset % align; 1133 if (r) 1134 new_offset += align - r; 1135 1136 dst_ehdr.e_phoff = new_offset; 1137 new_offset += dst_ehdr.e_phnum 1138 * dst_ehdr.e_phentsize; 1139 } 1140 /* UPDATE location of section header table */ 1141 if ((location(dst_ehdr.e_shoff, 0, src_elf) == AFTER) || 1142 ((location(dst_ehdr.e_shoff, 0, src_elf) == PRIOR) && 1143 (!Sect_exists && new_sec_string != NULL))) { 1144 r = new_offset % align; 1145 if (r) 1146 new_offset += align - r; 1147 1148 dst_ehdr.e_shoff = new_offset; 1149 } 1150 free(b_e_seg_table); 1151 1152 /* 1153 * The NOTE segment is the one segment whos 1154 * sections might get moved by mcs processing. 1155 * Make sure that the NOTE segments offset points 1156 * to the .note section. 1157 */ 1158 if ((notesegndx != -1) && (notesctndx != -1) && 1159 (sec_table[notesctndx].secno)) { 1160 Elf_Scn * notescn; 1161 GElf_Shdr nshdr; 1162 1163 notescn = elf_getscn(dst_elf, 1164 sec_table[notesctndx].secno); 1165 (void) gelf_getshdr(notescn, &nshdr); 1166 1167 if (gelf_getclass(dst_elf) == ELFCLASS32) { 1168 Elf32_Phdr * ph = elf32_getphdr(dst_elf) + 1169 notesegndx; 1170 /* LINTED */ 1171 ph->p_offset = (Elf32_Off)nshdr.sh_offset; 1172 } else { 1173 Elf64_Phdr * ph = elf64_getphdr(dst_elf) + 1174 notesegndx; 1175 ph->p_offset = (Elf64_Off)nshdr.sh_offset; 1176 } 1177 } 1178 } 1179 1180 /* copy ehdr changes back into real ehdr */ 1181 (void) gelf_update_ehdr(dst_elf, &dst_ehdr); 1182 if (elf_update(dst_elf, ELF_C_WRITE) < 0) { 1183 error_message(LIBELF_ERROR, 1184 LIBelf_ERROR, elf_errmsg(-1), prog); 1185 return (FAILURE); 1186 } 1187 1188 (void) elf_end(dst_elf); 1189 (void) close(fdtmp); 1190 return (SUCCESS); 1191 } 1192 1193 /* 1194 * Search through PHT saving the beginning and ending segment offsets 1195 */ 1196 static int 1197 build_segment_table(Elf * elf, GElf_Ehdr * ehdr) 1198 { 1199 unsigned int i; 1200 1201 if ((b_e_seg_table = (Seg_Table *) 1202 calloc(ehdr->e_phnum, sizeof (Seg_Table))) == NULL) { 1203 error_message(MALLOC_ERROR, 1204 PLAIN_ERROR, (char *)0, 1205 prog); 1206 mcs_exit(FAILURE); 1207 } 1208 1209 for (i = 0; i < ehdr->e_phnum; i++) { 1210 GElf_Phdr ph; 1211 1212 (void) gelf_getphdr(elf, i, &ph); 1213 1214 /* 1215 * remember the note SEGMENTS index so that we can 1216 * re-set it's p_offset later if needed. 1217 */ 1218 if (ph.p_type == PT_NOTE) 1219 notesegndx = i; 1220 1221 b_e_seg_table[i].p_offset = ph.p_offset; 1222 b_e_seg_table[i].p_memsz = ph.p_offset + ph.p_memsz; 1223 b_e_seg_table[i].p_filesz = ph.p_offset + ph.p_filesz; 1224 } 1225 return (SUCCESS); 1226 } 1227 1228 1229 static void 1230 copy_elf_file_to_temp_ar_file( 1231 int fdartmp, 1232 Elf_Arhdr *mem_header, 1233 char *cur_file) 1234 { 1235 char *buf; 1236 char mem_header_buf[sizeof (struct ar_hdr) + 1]; 1237 int fdtmp3; 1238 struct stat stbuf; 1239 1240 if ((fdtmp3 = open(elftmpfile, O_RDONLY)) == -1) { 1241 error_message(OPEN_TEMP_ERROR, 1242 SYSTEM_ERROR, strerror(errno), 1243 prog, elftmpfile); 1244 mcs_exit(FAILURE); 1245 } 1246 1247 (void) stat(elftmpfile, &stbuf); /* for size of file */ 1248 1249 if ((buf = 1250 malloc(ROUNDUP(stbuf.st_size))) == NULL) { 1251 error_message(MALLOC_ERROR, 1252 PLAIN_ERROR, (char *)0, 1253 prog); 1254 mcs_exit(FAILURE); 1255 } 1256 1257 if (read(fdtmp3, buf, stbuf.st_size) != stbuf.st_size) { 1258 error_message(READ_MANI_ERROR, 1259 SYSTEM_ERROR, strerror(errno), 1260 prog, elftmpfile, cur_file); 1261 mcs_exit(FAILURE); 1262 } 1263 1264 (void) sprintf(mem_header_buf, FORMAT, 1265 mem_header->ar_rawname, 1266 mem_header->ar_date, 1267 (unsigned)mem_header->ar_uid, 1268 (unsigned)mem_header->ar_gid, 1269 (unsigned)mem_header->ar_mode, 1270 stbuf.st_size, ARFMAG); 1271 1272 if (write(fdartmp, mem_header_buf, 1273 (unsigned)sizeof (struct ar_hdr)) != 1274 (unsigned)sizeof (struct ar_hdr)) { 1275 error_message(WRITE_MANI_ERROR, 1276 SYSTEM_ERROR, strerror(errno), 1277 prog, elftmpfile, cur_file); 1278 mcs_exit(FAILURE); 1279 } 1280 1281 if (stbuf.st_size & 0x1) { 1282 buf[stbuf.st_size] = '\n'; 1283 if (write(fdartmp, buf, (size_t)ROUNDUP(stbuf.st_size)) != 1284 (size_t)ROUNDUP(stbuf.st_size)) { 1285 error_message(WRITE_MANI_ERROR, 1286 SYSTEM_ERROR, strerror(errno), 1287 prog, elftmpfile, cur_file); 1288 mcs_exit(FAILURE); 1289 } 1290 } else if (write(fdartmp, buf, stbuf.st_size) != stbuf.st_size) { 1291 error_message(WRITE_MANI_ERROR, 1292 SYSTEM_ERROR, strerror(errno), 1293 prog, elftmpfile, cur_file); 1294 mcs_exit(FAILURE); 1295 } 1296 free(buf); 1297 (void) close(fdtmp3); 1298 } 1299 1300 static void 1301 copy_non_elf_to_temp_ar( 1302 int fd, 1303 Elf *elf, 1304 int fdartmp, 1305 Elf_Arhdr *mem_header, 1306 char *cur_file, 1307 Cmd_Info *cmd_info) 1308 { 1309 char mem_header_buf[sizeof (struct ar_hdr) + 1]; 1310 char *file_buf; 1311 1312 if (strcmp(mem_header->ar_name, "/") != 0) { 1313 (void) sprintf(mem_header_buf, FORMAT, 1314 mem_header->ar_rawname, 1315 mem_header->ar_date, 1316 (unsigned)mem_header->ar_uid, 1317 (unsigned)mem_header->ar_gid, 1318 (unsigned)mem_header->ar_mode, 1319 mem_header->ar_size, ARFMAG); 1320 1321 if (write(fdartmp, mem_header_buf, sizeof (struct ar_hdr)) != 1322 sizeof (struct ar_hdr)) { 1323 error_message(WRITE_MANI_ERROR, 1324 SYSTEM_ERROR, strerror(errno), 1325 prog, cur_file); 1326 mcs_exit(FAILURE); 1327 } 1328 if ((file_buf = 1329 malloc(ROUNDUP(mem_header->ar_size))) == NULL) { 1330 error_message(MALLOC_ERROR, 1331 PLAIN_ERROR, (char *)0, 1332 prog); 1333 mcs_exit(FAILURE); 1334 } 1335 1336 if (lseek(fd, elf_getbase(elf), 0) != elf_getbase(elf)) { 1337 error_message(WRITE_MANI_ERROR, 1338 prog, cur_file); 1339 mcs_exit(FAILURE); 1340 } 1341 1342 if (read(fd, file_buf, 1343 (size_t)ROUNDUP(mem_header->ar_size)) != 1344 (size_t)ROUNDUP(mem_header->ar_size)) { 1345 error_message(READ_MANI_ERROR, 1346 SYSTEM_ERROR, strerror(errno), 1347 prog, cur_file); 1348 mcs_exit(FAILURE); 1349 } 1350 if (write(fdartmp, 1351 file_buf, 1352 (size_t)ROUNDUP(mem_header->ar_size)) != 1353 (size_t)ROUNDUP(mem_header->ar_size)) { 1354 error_message(WRITE_MANI_ERROR, 1355 SYSTEM_ERROR, strerror(errno), 1356 prog, cur_file); 1357 mcs_exit(FAILURE); 1358 } 1359 free(file_buf); 1360 } else if (CHK_OPT(cmd_info, MIGHT_CHG)) { 1361 error_message(SYM_TAB_AR_ERROR, 1362 PLAIN_ERROR, (char *)0, 1363 prog, cur_file); 1364 error_message(EXEC_AR_ERROR, 1365 PLAIN_ERROR, (char *)0, 1366 cur_file); 1367 } 1368 } 1369 1370 static void 1371 copy_file(int ofd, char *fname, char *temp_file_name) 1372 { 1373 int i; 1374 int fdtmp2; 1375 struct stat stbuf; 1376 char *buf; 1377 1378 for (i = 0; signum[i]; i++) /* started writing, cannot interrupt */ 1379 (void) signal(signum[i], SIG_IGN); 1380 1381 if ((fdtmp2 = open(temp_file_name, O_RDONLY)) == -1) { 1382 error_message(OPEN_TEMP_ERROR, 1383 SYSTEM_ERROR, strerror(errno), 1384 prog, temp_file_name); 1385 mcs_exit(FAILURE); 1386 } 1387 1388 (void) stat(temp_file_name, &stbuf); /* for size of file */ 1389 1390 /* 1391 * Get the contents of the updated file. 1392 * First try mmap()'ing. If mmap() fails, 1393 * then use the malloc() and read(). 1394 */ 1395 i = MMAP_USED; 1396 if ((buf = (char *)mmap(0, stbuf.st_size, 1397 PROT_READ, MAP_SHARED, fdtmp2, 0)) == (caddr_t)-1) { 1398 if ((buf = 1399 malloc(stbuf.st_size * sizeof (char))) == NULL) { 1400 error_message(MALLOC_ERROR, 1401 PLAIN_ERROR, (char *)0, 1402 prog); 1403 mcs_exit(FAILURE); 1404 } 1405 1406 if (read(fdtmp2, buf, stbuf.st_size) != stbuf.st_size) { 1407 error_message(READ_SYS_ERROR, 1408 SYSTEM_ERROR, strerror(errno), 1409 prog, temp_file_name); 1410 mcs_exit(FAILURE); 1411 } 1412 i = MMAP_UNUSED; 1413 } 1414 1415 if (ftruncate(ofd, 0) == -1) { 1416 error_message(WRITE_MANI_ERROR2, 1417 SYSTEM_ERROR, strerror(errno), 1418 prog, fname); 1419 mcs_exit(FAILURE); 1420 } 1421 if (lseek(ofd, 0, SEEK_SET) == -1) { 1422 error_message(WRITE_MANI_ERROR2, 1423 SYSTEM_ERROR, strerror(errno), 1424 prog, fname); 1425 mcs_exit(FAILURE); 1426 } 1427 if ((write(ofd, buf, stbuf.st_size)) != stbuf.st_size) { 1428 error_message(WRITE_MANI_ERROR2, 1429 SYSTEM_ERROR, strerror(errno), 1430 prog, fname); 1431 mcs_exit(FAILURE); 1432 } 1433 1434 /* 1435 * clean 1436 */ 1437 if (i == MMAP_USED) 1438 (void) munmap(buf, stbuf.st_size); 1439 else 1440 free(buf); 1441 (void) close(fdtmp2); 1442 (void) unlink(temp_file_name); /* temp file */ 1443 } 1444 1445 static uint64_t 1446 location(int64_t offset, int mem_search, Elf * elf) 1447 { 1448 int i; 1449 uint64_t upper; 1450 GElf_Ehdr ehdr; 1451 1452 (void) gelf_getehdr(elf, &ehdr); 1453 1454 for (i = 0; i < ehdr.e_phnum; i++) { 1455 if (mem_search) 1456 upper = b_e_seg_table[i].p_memsz; 1457 else 1458 upper = b_e_seg_table[i].p_filesz; 1459 if ((offset >= b_e_seg_table[i].p_offset) && 1460 (offset <= upper)) 1461 return (IN); 1462 else if (offset < b_e_seg_table[i].p_offset) 1463 return (PRIOR); 1464 } 1465 return (AFTER); 1466 } 1467 1468 static uint64_t 1469 scn_location(Elf_Scn * scn, Elf * elf) 1470 { 1471 GElf_Shdr shdr; 1472 1473 (void) gelf_getshdr(scn, &shdr); 1474 1475 /* 1476 * If the section is not a NOTE section and it has no 1477 * virtual address then it is not part of a mapped segment. 1478 */ 1479 if (shdr.sh_addr == 0) 1480 return (location(shdr.sh_offset + shdr.sh_size, 0, elf)); 1481 1482 return (location(shdr.sh_offset + shdr.sh_size, 1, elf)); 1483 } 1484 1485 static void 1486 initialize(int shnum, Cmd_Info *cmd_info) 1487 { 1488 /* 1489 * Initialize command info 1490 */ 1491 cmd_info->no_of_append = cmd_info->no_of_delete = 1492 cmd_info->no_of_nulled = cmd_info->no_of_compressed = 1493 cmd_info->no_of_moved = 0; 1494 cmd_info->sh_groups.head = cmd_info->sh_groups.tail = 0; 1495 1496 if ((sec_table = (section_info_table *) 1497 calloc(shnum + 1, 1498 sizeof (section_info_table))) == NULL) { 1499 error_message(MALLOC_ERROR, 1500 PLAIN_ERROR, (char *)0, 1501 prog); 1502 exit(FAILURE); 1503 } 1504 1505 if ((off_table = (int64_t *) 1506 calloc(shnum, 1507 sizeof (int64_t))) == NULL) { 1508 error_message(MALLOC_ERROR, 1509 PLAIN_ERROR, (char *)0, 1510 prog); 1511 exit(FAILURE); 1512 } 1513 1514 if ((nobits_table = (int64_t *) 1515 calloc(shnum, sizeof (int64_t))) == NULL) { 1516 error_message(MALLOC_ERROR, 1517 PLAIN_ERROR, (char *)0, 1518 prog); 1519 exit(FAILURE); 1520 } 1521 } 1522 1523 /* 1524 * Update the contents of SHT_GROUP if needed 1525 */ 1526 void 1527 post_process(Cmd_Info *cmd_info) 1528 { 1529 Listnode * lnp, *plnp; 1530 section_info_table * sinfo; 1531 Word * grpdata, *ngrpdata; 1532 int64_t sno, sno2; 1533 Word i, j, num; 1534 1535 /* 1536 * If no change is required, then return. 1537 */ 1538 if ((cmd_info->flags & (SHF_GROUP_MOVE|SHF_GROUP_DEL)) == 0) 1539 return; 1540 1541 /* 1542 * If SHF_GROUP sections were removed, we might need to 1543 * remove SHT_GROUP sections. 1544 */ 1545 if (cmd_info->flags & SHF_GROUP_DEL) { 1546 Word grpcnt; 1547 int deleted = 0; 1548 1549 for (LIST_TRAVERSE(&cmd_info->sh_groups, lnp, sinfo)) { 1550 if (sinfo->secno == (GElf_Word)DELETED) 1551 continue; 1552 num = (sinfo->shdr).sh_size/sizeof (Word); 1553 grpcnt = 0; 1554 grpdata = (Word *)(sinfo->data->d_buf); 1555 for (i = 1; i < num; i++) { 1556 if (sec_table[grpdata[i]].secno != 1557 (GElf_Word)DELETED) 1558 grpcnt++; 1559 } 1560 1561 /* 1562 * All members in this SHT_GROUP were removed. 1563 * We can remove this SHT_GROUP. 1564 */ 1565 if (grpcnt == 0) { 1566 sinfo->secno = (GElf_Word)DELETED; 1567 (cmd_info->no_of_delete)++; 1568 deleted = 1; 1569 } 1570 } 1571 1572 /* 1573 * If we deleted a SHT_GROUP section, 1574 * we need to reasign section numbers. 1575 */ 1576 if (deleted) { 1577 section_info_table *sinfo; 1578 1579 sno = 1; 1580 sno2 = 1; 1581 while (sec_table[sno].scn != (Elf_Scn *)-1) { 1582 sinfo = &sec_table[sno]; 1583 if (sinfo->secno != (GElf_Word) DELETED) 1584 sinfo->secno = sno2++; 1585 sno++; 1586 } 1587 } 1588 } 1589 1590 /* 1591 * Now we can update data buffers of the 1592 * SHT_GROUP sections. 1593 */ 1594 plnp = 0; 1595 for (LIST_TRAVERSE(&cmd_info->sh_groups, lnp, sinfo)) { 1596 if (plnp) 1597 free(plnp); 1598 plnp = lnp; 1599 if (sinfo->secno == (GElf_Word)DELETED) 1600 continue; 1601 num = (sinfo->shdr).sh_size/sizeof (Word); 1602 1603 /* 1604 * Need to generate the updated data buffer 1605 */ 1606 if ((sinfo->mdata = malloc(sizeof (Elf_Data))) == NULL) { 1607 error_message(MALLOC_ERROR, 1608 PLAIN_ERROR, (char *)0, 1609 prog); 1610 exit(FAILURE); 1611 } 1612 *(sinfo->mdata) = *(sinfo->data); 1613 if ((ngrpdata = sinfo->mdata->d_buf = 1614 malloc(sinfo->data->d_size)) == NULL) { 1615 error_message(MALLOC_ERROR, 1616 PLAIN_ERROR, (char *)0, 1617 prog); 1618 exit(FAILURE); 1619 } 1620 1621 grpdata = (Word *)(sinfo->data->d_buf); 1622 ngrpdata[0] = grpdata[0]; 1623 j = 1; 1624 for (i = 1; i < num; i++) { 1625 if (sec_table[grpdata[i]].secno != (GElf_Word)DELETED) { 1626 ngrpdata[j++] = sec_table[grpdata[i]].secno; 1627 } 1628 } 1629 sinfo->mdata->d_size = j * sizeof (Word); 1630 sinfo->data = sinfo->mdata; 1631 } 1632 if (plnp) 1633 free(plnp); 1634 } 1635