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