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