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