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