17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T 247c478bd9Sstevel@tonic-gate * All Rights Reserved 257c478bd9Sstevel@tonic-gate * 26*ba7866cdSAli Bahrami * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <errno.h> 3057ef7aa9SRod Evans #include "alist.h" 317c478bd9Sstevel@tonic-gate #include "mcs.h" 327c478bd9Sstevel@tonic-gate #include "extern.h" 337c478bd9Sstevel@tonic-gate #include "gelf.h" 347c478bd9Sstevel@tonic-gate 350d15df17Sab196087 /* 360d15df17Sab196087 * Type used to pass state information for the current 370d15df17Sab196087 * file between routines. 380d15df17Sab196087 */ 390d15df17Sab196087 typedef struct { 400d15df17Sab196087 int Sect_exists; 410d15df17Sab196087 int notesegndx; 420d15df17Sab196087 int notesctndx; 430d15df17Sab196087 Seg_Table *b_e_seg_table; 440d15df17Sab196087 section_info_table *sec_table; 450d15df17Sab196087 int64_t *off_table; /* maintains section's offset; set to */ 460d15df17Sab196087 /* retain old offset, else 0 */ 470d15df17Sab196087 int64_t *nobits_table; /* maintains NOBITS sections */ 480d15df17Sab196087 char *new_sec_string; 490d15df17Sab196087 } file_state_t; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate /* 537c478bd9Sstevel@tonic-gate * Function prototypes. 547c478bd9Sstevel@tonic-gate */ 55d1477c77SAli Bahrami static void copy_file(int, char *, Tmp_File *); 567c478bd9Sstevel@tonic-gate static void 577c478bd9Sstevel@tonic-gate copy_non_elf_to_temp_ar(int, Elf *, int, Elf_Arhdr *, char *, Cmd_Info *); 587c478bd9Sstevel@tonic-gate static void copy_elf_file_to_temp_ar_file(int, Elf_Arhdr *, char *); 597c478bd9Sstevel@tonic-gate static int process_file(Elf *, char *, Cmd_Info *); 600d15df17Sab196087 static void initialize(int shnum, Cmd_Info *, file_state_t *); 610d15df17Sab196087 static int build_segment_table(Elf*, GElf_Ehdr *, file_state_t *); 620d15df17Sab196087 static int traverse_file(Elf *, GElf_Ehdr *, char *, Cmd_Info *, 630d15df17Sab196087 file_state_t *); 640d15df17Sab196087 static uint64_t location(int64_t, int, Elf *, file_state_t *); 650d15df17Sab196087 static uint64_t scn_location(Elf_Scn *, Elf *, file_state_t *); 660d15df17Sab196087 static int build_file(Elf *, GElf_Ehdr *, Cmd_Info *, file_state_t *); 670d15df17Sab196087 static void post_process(Cmd_Info *, file_state_t *); 680d15df17Sab196087 690d15df17Sab196087 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate int 727c478bd9Sstevel@tonic-gate each_file(char *cur_file, Cmd_Info *cmd_info) 737c478bd9Sstevel@tonic-gate { 747c478bd9Sstevel@tonic-gate Elf *elf = 0; 757c478bd9Sstevel@tonic-gate Elf_Cmd cmd; 767c478bd9Sstevel@tonic-gate Elf *arf = 0; 777c478bd9Sstevel@tonic-gate Elf_Arhdr *mem_header; 787c478bd9Sstevel@tonic-gate char *cur_filenm = NULL; 797c478bd9Sstevel@tonic-gate int code = 0; 807c478bd9Sstevel@tonic-gate int error = 0, err = 0; 817c478bd9Sstevel@tonic-gate int ar_file = 0; 827c478bd9Sstevel@tonic-gate int fdartmp; 837c478bd9Sstevel@tonic-gate int fd; 847c478bd9Sstevel@tonic-gate int oflag; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate if (cmd_info->flags & MIGHT_CHG) 877c478bd9Sstevel@tonic-gate oflag = O_RDWR; 887c478bd9Sstevel@tonic-gate else 897c478bd9Sstevel@tonic-gate oflag = O_RDONLY; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate if ((fd = open(cur_file, oflag)) == -1) { 920d15df17Sab196087 error_message(OPEN_ERROR, SYSTEM_ERROR, strerror(errno), 930d15df17Sab196087 prog, cur_file); 947c478bd9Sstevel@tonic-gate return (FAILURE); 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * Note, elf_begin requires ELF_C_READ even if MIGHT_CHK is in effect. 997c478bd9Sstevel@tonic-gate * libelf does not allow elf_begin() with ELF_C_RDWR when processing 1007c478bd9Sstevel@tonic-gate * archive file members. Because we are limited to ELF_C_READ use, any 1017c478bd9Sstevel@tonic-gate * ELF data modification must be provided by updating a copy of 1027c478bd9Sstevel@tonic-gate * the data, rather than updating the original file data. 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate cmd = ELF_C_READ; 10557ef7aa9SRod Evans if ((arf = elf_begin(fd, cmd, NULL)) == NULL) { 1060d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 1077c478bd9Sstevel@tonic-gate (void) elf_end(arf); 1087c478bd9Sstevel@tonic-gate (void) close(fd); /* done processing this file */ 1097c478bd9Sstevel@tonic-gate return (FAILURE); 1107c478bd9Sstevel@tonic-gate } 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate if ((elf_kind(arf) == ELF_K_AR)) { 1137c478bd9Sstevel@tonic-gate ar_file = 1; 1147c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, MIGHT_CHG)) { 115d1477c77SAli Bahrami artmpfile.tmp_name = tempnam(TMPDIR, "mcs2"); 116d1477c77SAli Bahrami if ((fdartmp = open(artmpfile.tmp_name, 1177c478bd9Sstevel@tonic-gate O_WRONLY | O_APPEND | O_CREAT, 1187c478bd9Sstevel@tonic-gate (mode_t)0666)) == NULL) { 1197c478bd9Sstevel@tonic-gate error_message(OPEN_TEMP_ERROR, 1207c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), 1217c478bd9Sstevel@tonic-gate prog, artmpfile); 1227c478bd9Sstevel@tonic-gate (void) elf_end(arf); 1237c478bd9Sstevel@tonic-gate (void) close(fd); 124d1477c77SAli Bahrami mcs_exit(FAILURE); 1257c478bd9Sstevel@tonic-gate } 126d1477c77SAli Bahrami artmpfile.tmp_unlink = 1; 1277c478bd9Sstevel@tonic-gate /* write magic string to artmpfile */ 1287c478bd9Sstevel@tonic-gate if ((write(fdartmp, ARMAG, SARMAG)) != SARMAG) { 1297c478bd9Sstevel@tonic-gate error_message(WRITE_ERROR, 1307c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), 131d1477c77SAli Bahrami prog, artmpfile.tmp_name, cur_file); 1327c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate } else { 1367c478bd9Sstevel@tonic-gate ar_file = 0; 1377c478bd9Sstevel@tonic-gate cur_filenm = cur_file; 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* 1417c478bd9Sstevel@tonic-gate * Holds temporary file; 1427c478bd9Sstevel@tonic-gate * if archive, holds the current member file if it has an ehdr, 1437c478bd9Sstevel@tonic-gate * and there were no errors in 1447c478bd9Sstevel@tonic-gate * processing the object file. 1457c478bd9Sstevel@tonic-gate */ 146d1477c77SAli Bahrami elftmpfile.tmp_name = tempnam(TMPDIR, "mcs1"); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate while ((elf = elf_begin(fd, cmd, arf)) != 0) { 1497c478bd9Sstevel@tonic-gate if (ar_file) /* get header info */ { 1505aefb655Srie size_t len; 1515aefb655Srie 1527c478bd9Sstevel@tonic-gate if ((mem_header = elf_getarhdr(elf)) == NULL) { 1530d15df17Sab196087 error_message(GETARHDR_ERROR, LIBelf_ERROR, 1540d15df17Sab196087 elf_errmsg(-1), prog, cur_file, 1550d15df17Sab196087 elf_getbase(elf)); 1567c478bd9Sstevel@tonic-gate (void) elf_end(elf); 1577c478bd9Sstevel@tonic-gate (void) elf_end(arf); 1587c478bd9Sstevel@tonic-gate (void) close(fd); 159d1477c77SAli Bahrami free_tempfile(&artmpfile); 1607c478bd9Sstevel@tonic-gate return (FAILURE); 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate if (cur_filenm != NULL) 1647c478bd9Sstevel@tonic-gate free(cur_filenm); 1655aefb655Srie 1665aefb655Srie len = (strlen(cur_file) + 3 + 1675aefb655Srie strlen(mem_header->ar_name)); 1685aefb655Srie 1695aefb655Srie if ((cur_filenm = malloc(len)) == NULL) { 1707c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 17157ef7aa9SRod Evans PLAIN_ERROR, NULL, prog); 1727c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1755aefb655Srie (void) snprintf(cur_filenm, len, "%s[%s]", 1767c478bd9Sstevel@tonic-gate cur_file, mem_header->ar_name); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate if (elf_kind(elf) == ELF_K_ELF) { 1807c478bd9Sstevel@tonic-gate if ((code = process_file(elf, cur_filenm, cmd_info)) == 1817c478bd9Sstevel@tonic-gate FAILURE) { 1827c478bd9Sstevel@tonic-gate if (!ar_file) { 1837c478bd9Sstevel@tonic-gate (void) elf_end(arf); 1847c478bd9Sstevel@tonic-gate (void) elf_end(elf); 1857c478bd9Sstevel@tonic-gate (void) close(fd); 1867c478bd9Sstevel@tonic-gate return (FAILURE); 1877c478bd9Sstevel@tonic-gate } else { 1880d15df17Sab196087 copy_non_elf_to_temp_ar(fd, elf, 1890d15df17Sab196087 fdartmp, mem_header, 1907c478bd9Sstevel@tonic-gate cur_file, cmd_info); 1917c478bd9Sstevel@tonic-gate error++; 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate } else if (ar_file && CHK_OPT(cmd_info, MIGHT_CHG)) { 1947c478bd9Sstevel@tonic-gate if (code == DONT_BUILD) 1950d15df17Sab196087 copy_non_elf_to_temp_ar(fd, elf, 1960d15df17Sab196087 fdartmp, mem_header, 1977c478bd9Sstevel@tonic-gate cur_file, cmd_info); 1987c478bd9Sstevel@tonic-gate else 1997c478bd9Sstevel@tonic-gate copy_elf_file_to_temp_ar_file( 2007c478bd9Sstevel@tonic-gate fdartmp, mem_header, cur_file); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate } else { 2037c478bd9Sstevel@tonic-gate /* 2047c478bd9Sstevel@tonic-gate * decide what to do with non-ELF file 2057c478bd9Sstevel@tonic-gate */ 2067c478bd9Sstevel@tonic-gate if (!ar_file) { 2070d15df17Sab196087 error_message(FILE_TYPE_ERROR, PLAIN_ERROR, 20857ef7aa9SRod Evans NULL, prog, cur_filenm); 2097c478bd9Sstevel@tonic-gate (void) close(fd); 2107c478bd9Sstevel@tonic-gate return (FAILURE); 2117c478bd9Sstevel@tonic-gate } else { 2127c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, MIGHT_CHG)) 2130d15df17Sab196087 copy_non_elf_to_temp_ar(fd, elf, 2140d15df17Sab196087 fdartmp, mem_header, 2157c478bd9Sstevel@tonic-gate cur_file, cmd_info); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate cmd = elf_next(elf); 2197c478bd9Sstevel@tonic-gate (void) elf_end(elf); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate err = elf_errno(); 2237c478bd9Sstevel@tonic-gate if (err != 0) { 2240d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, 2250d15df17Sab196087 elf_errmsg(err), prog); 22657ef7aa9SRod Evans error_message(NOT_MANIPULATED_ERROR, PLAIN_ERROR, NULL, 2277c478bd9Sstevel@tonic-gate prog, cur_file); 2287c478bd9Sstevel@tonic-gate return (FAILURE); 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate (void) elf_end(arf); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate if (ar_file && CHK_OPT(cmd_info, MIGHT_CHG)) { 2347c478bd9Sstevel@tonic-gate (void) close(fdartmp); /* done writing to ar_temp_file */ 2357c478bd9Sstevel@tonic-gate /* copy ar_temp_file to FILE */ 236d1477c77SAli Bahrami copy_file(fd, cur_file, &artmpfile); 2377c478bd9Sstevel@tonic-gate } else if (code != DONT_BUILD && CHK_OPT(cmd_info, MIGHT_CHG)) 238d1477c77SAli Bahrami copy_file(fd, cur_file, &elftmpfile); 2397c478bd9Sstevel@tonic-gate (void) close(fd); /* done processing this file */ 2407c478bd9Sstevel@tonic-gate return (error); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate static int 2447c478bd9Sstevel@tonic-gate process_file(Elf *elf, char *cur_file, Cmd_Info *cmd_info) 2457c478bd9Sstevel@tonic-gate { 2467c478bd9Sstevel@tonic-gate int error = SUCCESS; 2477c478bd9Sstevel@tonic-gate int x; 2487c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr; 2497c478bd9Sstevel@tonic-gate size_t shnum; 2500d15df17Sab196087 file_state_t state; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate /* 2537c478bd9Sstevel@tonic-gate * Initialize 2547c478bd9Sstevel@tonic-gate */ 2557c478bd9Sstevel@tonic-gate if (gelf_getehdr(elf, &ehdr) == NULL) { 2560d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 2577c478bd9Sstevel@tonic-gate return (FAILURE); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 26062b628a6SAli Bahrami if (elf_getshdrnum(elf, &shnum) == -1) { 2610d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 2627c478bd9Sstevel@tonic-gate return (FAILURE); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate 2650d15df17Sab196087 /* Initialize per-file state */ 2660d15df17Sab196087 state.Sect_exists = 0; 2670d15df17Sab196087 state.notesegndx = -1; 2680d15df17Sab196087 state.notesctndx = -1; 2690d15df17Sab196087 state.b_e_seg_table = NULL; 2700d15df17Sab196087 state.sec_table = NULL; 2710d15df17Sab196087 state.off_table = 0; 2720d15df17Sab196087 state.nobits_table = NULL; 2730d15df17Sab196087 state.new_sec_string = NULL; 2747c478bd9Sstevel@tonic-gate 2750d15df17Sab196087 initialize(shnum, cmd_info, &state); 2767c478bd9Sstevel@tonic-gate 2770d15df17Sab196087 if ((ehdr.e_phnum != 0) && 2780d15df17Sab196087 (build_segment_table(elf, &ehdr, &state) == FAILURE)) { 2790d15df17Sab196087 x = error = FAILURE; 2800d15df17Sab196087 } else if ((x = traverse_file(elf, &ehdr, cur_file, 2810d15df17Sab196087 cmd_info, &state)) == FAILURE) { 28257ef7aa9SRod Evans error_message(WRN_MANIPULATED_ERROR, PLAIN_ERROR, NULL, 2837c478bd9Sstevel@tonic-gate prog, cur_file); 2847c478bd9Sstevel@tonic-gate error = FAILURE; 2857c478bd9Sstevel@tonic-gate } else if (x != DONT_BUILD && x != FAILURE) { 2860d15df17Sab196087 post_process(cmd_info, &state); 2870d15df17Sab196087 if (build_file(elf, &ehdr, cmd_info, &state) == FAILURE) { 2880d15df17Sab196087 error_message(WRN_MANIPULATED_ERROR, PLAIN_ERROR, 28957ef7aa9SRod Evans NULL, prog, cur_file); 2907c478bd9Sstevel@tonic-gate error = FAILURE; 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2940d15df17Sab196087 /* Release any dynamicaly allocated buffers */ 2950d15df17Sab196087 if (state.b_e_seg_table != NULL) 2960d15df17Sab196087 free(state.b_e_seg_table); 2970d15df17Sab196087 if (state.sec_table != NULL) 2980d15df17Sab196087 free(state.sec_table); 2990d15df17Sab196087 if (state.off_table != NULL) 3000d15df17Sab196087 free(state.off_table); 3010d15df17Sab196087 if (state.nobits_table != NULL) 3020d15df17Sab196087 free(state.nobits_table); 3030d15df17Sab196087 if (state.new_sec_string != NULL) 3040d15df17Sab196087 free(state.new_sec_string); 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if (x == DONT_BUILD) 3077c478bd9Sstevel@tonic-gate return (DONT_BUILD); 3087c478bd9Sstevel@tonic-gate else 3097c478bd9Sstevel@tonic-gate return (error); 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate static int 3130d15df17Sab196087 traverse_file(Elf *elf, GElf_Ehdr * ehdr, char *cur_file, Cmd_Info *cmd_info, 3140d15df17Sab196087 file_state_t *state) 3157c478bd9Sstevel@tonic-gate { 3167c478bd9Sstevel@tonic-gate Elf_Scn * scn; 3177c478bd9Sstevel@tonic-gate Elf_Scn * temp_scn; 3187c478bd9Sstevel@tonic-gate Elf_Data * data; 3197c478bd9Sstevel@tonic-gate GElf_Shdr * shdr; 3207c478bd9Sstevel@tonic-gate char *temp_name; 3217c478bd9Sstevel@tonic-gate section_info_table * sinfo; 3227c478bd9Sstevel@tonic-gate GElf_Xword x; 3237c478bd9Sstevel@tonic-gate int ret = 0, SYM = 0; /* used by strip command */ 3247c478bd9Sstevel@tonic-gate int phnum = ehdr->e_phnum; 3257c478bd9Sstevel@tonic-gate unsigned int i, scn_index; 3267c478bd9Sstevel@tonic-gate size_t shstrndx, shnum; 3277c478bd9Sstevel@tonic-gate 3280d15df17Sab196087 state->Sect_exists = 0; 3297c478bd9Sstevel@tonic-gate 33062b628a6SAli Bahrami if (elf_getshdrnum(elf, &shnum) == -1) { 3310d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 3327c478bd9Sstevel@tonic-gate return (FAILURE); 3337c478bd9Sstevel@tonic-gate } 33462b628a6SAli Bahrami if (elf_getshdrstrndx(elf, &shstrndx) == -1) { 3350d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 3367c478bd9Sstevel@tonic-gate return (FAILURE); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate scn = 0; 3407c478bd9Sstevel@tonic-gate scn_index = 1; 3410d15df17Sab196087 sinfo = &state->sec_table[scn_index]; 3427c478bd9Sstevel@tonic-gate while ((scn = elf_nextscn(elf, scn)) != 0) { 3437c478bd9Sstevel@tonic-gate char *name; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate shdr = &(sinfo->shdr); 3467c478bd9Sstevel@tonic-gate if (gelf_getshdr(scn, shdr) == NULL) { 3477c478bd9Sstevel@tonic-gate error_message(NO_SECT_TABLE_ERROR, 3480d15df17Sab196087 LIBelf_ERROR, elf_errmsg(-1), prog, cur_file); 3497c478bd9Sstevel@tonic-gate return (FAILURE); 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 3520d15df17Sab196087 /* 3530d15df17Sab196087 * Note: If the object has problems, name 3540d15df17Sab196087 * may be set to NULL by the following. 3550d15df17Sab196087 */ 3560d15df17Sab196087 name = elf_strptr(elf, shstrndx, (size_t)shdr->sh_name); 3570d15df17Sab196087 3587c478bd9Sstevel@tonic-gate sinfo->scn = scn; 3597c478bd9Sstevel@tonic-gate sinfo->secno = scn_index; 3607c478bd9Sstevel@tonic-gate sinfo->osecno = scn_index; 3617c478bd9Sstevel@tonic-gate SET_ACTION(sinfo->flags, ACT_NOP); 3627c478bd9Sstevel@tonic-gate sinfo->name = name; 3637c478bd9Sstevel@tonic-gate if (ehdr->e_phnum == 0) 3647c478bd9Sstevel@tonic-gate SET_LOC(sinfo->flags, NOSEG); 3657c478bd9Sstevel@tonic-gate else 3660d15df17Sab196087 SET_LOC(sinfo->flags, scn_location(scn, elf, state)); 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate if (shdr->sh_type == SHT_GROUP) { 36957ef7aa9SRod Evans if (aplist_append(&cmd_info->sh_groups, 37057ef7aa9SRod Evans sinfo, 10) == NULL) { 3710d15df17Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR, 37257ef7aa9SRod Evans NULL, prog); 3737c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /* 3787c478bd9Sstevel@tonic-gate * If the target section is pointed by a section 3797c478bd9Sstevel@tonic-gate * holding relocation infomation, then the 3807c478bd9Sstevel@tonic-gate * pointing section would be useless if the 3817c478bd9Sstevel@tonic-gate * target section is removed. 3827c478bd9Sstevel@tonic-gate */ 3837c478bd9Sstevel@tonic-gate if ((shdr->sh_type == SHT_REL || 3847c478bd9Sstevel@tonic-gate shdr->sh_type == SHT_RELA) && 3857c478bd9Sstevel@tonic-gate (shdr->sh_info != SHN_UNDEF && 3867c478bd9Sstevel@tonic-gate (temp_scn = elf_getscn(elf, shdr->sh_info)) != 0)) { 3877c478bd9Sstevel@tonic-gate GElf_Shdr tmp_shdr; 3887c478bd9Sstevel@tonic-gate if (gelf_getshdr(temp_scn, &tmp_shdr) != NULL) { 3897c478bd9Sstevel@tonic-gate temp_name = elf_strptr(elf, shstrndx, 3907c478bd9Sstevel@tonic-gate (size_t)tmp_shdr.sh_name); 3917c478bd9Sstevel@tonic-gate sinfo->rel_name = temp_name; 3927c478bd9Sstevel@tonic-gate sinfo->rel_scn_index = 3937c478bd9Sstevel@tonic-gate shdr->sh_info; 3947c478bd9Sstevel@tonic-gate if (phnum == 0) 3957c478bd9Sstevel@tonic-gate sinfo->rel_loc = NOSEG; 3967c478bd9Sstevel@tonic-gate else 3977c478bd9Sstevel@tonic-gate sinfo->rel_loc = 3980d15df17Sab196087 scn_location(temp_scn, elf, state); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate data = 0; 4027c478bd9Sstevel@tonic-gate if ((data = elf_getdata(scn, data)) == NULL) { 4037c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 4047c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 4057c478bd9Sstevel@tonic-gate return (FAILURE); 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate sinfo->data = data; 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate /* 4107c478bd9Sstevel@tonic-gate * Check if this section is a candidate for 4117c478bd9Sstevel@tonic-gate * action to be processes. 4127c478bd9Sstevel@tonic-gate */ 4130d15df17Sab196087 if ((name != NULL) && (sectcmp(name) == 0)) { 4147c478bd9Sstevel@tonic-gate SET_CANDIDATE(sinfo->flags); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* 4177c478bd9Sstevel@tonic-gate * This flag just shows that there was a 4187c478bd9Sstevel@tonic-gate * candidate. 4197c478bd9Sstevel@tonic-gate */ 4200d15df17Sab196087 state->Sect_exists++; 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /* 4247c478bd9Sstevel@tonic-gate * Any of the following section types should 4257c478bd9Sstevel@tonic-gate * also be removed (if possible) if invoked via 4267c478bd9Sstevel@tonic-gate * the 'strip' command. 4277c478bd9Sstevel@tonic-gate */ 4287c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, I_AM_STRIP) && 4297c478bd9Sstevel@tonic-gate ((shdr->sh_type == SHT_SUNW_DEBUG) || 4307c478bd9Sstevel@tonic-gate (shdr->sh_type == SHT_SUNW_DEBUGSTR))) { 4317c478bd9Sstevel@tonic-gate SET_CANDIDATE(sinfo->flags); 4320d15df17Sab196087 state->Sect_exists++; 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * Zap this file ? 4387c478bd9Sstevel@tonic-gate */ 4397c478bd9Sstevel@tonic-gate if ((cmd_info->flags & zFLAG) && 4407c478bd9Sstevel@tonic-gate (shdr->sh_type == SHT_PROGBITS)) { 4417c478bd9Sstevel@tonic-gate SET_CANDIDATE(sinfo->flags); 4420d15df17Sab196087 state->Sect_exists++; 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate x = GET_LOC(sinfo->flags); 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* 4470d15df17Sab196087 * Remember the note section index so that we can 4480d15df17Sab196087 * reset the NOTE segment offset to point to it. Depending 4490d15df17Sab196087 * on the operation being carried out, the note section may 4500d15df17Sab196087 * be assigned a new location in the resulting ELF 4510d15df17Sab196087 * image, and the program header needs to reflect that. 4527c478bd9Sstevel@tonic-gate * 4530d15df17Sab196087 * There can be multiple contiguous note sections in 4540d15df17Sab196087 * an object, referenced by a single NOTE segment. We 4550d15df17Sab196087 * want to be sure and remember the one referenced by 4560d15df17Sab196087 * the program header, and not one of the others. 4577c478bd9Sstevel@tonic-gate */ 4580d15df17Sab196087 if ((shdr->sh_type == SHT_NOTE) && (state->notesctndx == -1) && 4590d15df17Sab196087 (state->notesegndx != -1) && 4600d15df17Sab196087 (state->b_e_seg_table[state->notesegndx].p_offset 4610d15df17Sab196087 == shdr->sh_offset)) 4620d15df17Sab196087 state->notesctndx = scn_index; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate if (x == IN || x == PRIOR) 4650d15df17Sab196087 state->off_table[scn_index] = shdr->sh_offset; 4667c478bd9Sstevel@tonic-gate if (shdr->sh_type == SHT_NOBITS) 4670d15df17Sab196087 state->nobits_table[scn_index] = 1; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * If this section satisfies the condition, 4717c478bd9Sstevel@tonic-gate * apply the actions specified. 4727c478bd9Sstevel@tonic-gate */ 4737c478bd9Sstevel@tonic-gate if (ISCANDIDATE(sinfo->flags)) { 4747c478bd9Sstevel@tonic-gate ret += apply_action(sinfo, cur_file, cmd_info); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * If I am strip command, determine if symtab can go or not. 4797c478bd9Sstevel@tonic-gate */ 4807c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, I_AM_STRIP) && 4817c478bd9Sstevel@tonic-gate (CHK_OPT(cmd_info, xFLAG) == 0) && 4827c478bd9Sstevel@tonic-gate (CHK_OPT(cmd_info, lFLAG) == 0)) { 4837c478bd9Sstevel@tonic-gate if (shdr->sh_type == SHT_SYMTAB && 4847c478bd9Sstevel@tonic-gate GET_LOC(sinfo->flags) == AFTER) { 4857c478bd9Sstevel@tonic-gate SYM = scn_index; 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate scn_index++; 4897c478bd9Sstevel@tonic-gate sinfo++; 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate sinfo->scn = (Elf_Scn *) -1; 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* 4947c478bd9Sstevel@tonic-gate * If there were any errors traversing the file, 4957c478bd9Sstevel@tonic-gate * just return error. 4967c478bd9Sstevel@tonic-gate */ 4977c478bd9Sstevel@tonic-gate if (ret != 0) 4987c478bd9Sstevel@tonic-gate return (FAILURE); 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate /* 5017c478bd9Sstevel@tonic-gate * Remove symbol table if possible 5027c478bd9Sstevel@tonic-gate */ 5037c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, I_AM_STRIP) && SYM != 0) { 5047c478bd9Sstevel@tonic-gate GElf_Shdr tmp_shdr; 5057c478bd9Sstevel@tonic-gate 5060d15df17Sab196087 (void) gelf_getshdr(state->sec_table[SYM].scn, &tmp_shdr); 5070d15df17Sab196087 state->sec_table[SYM].secno = (GElf_Word)DELETED; 5087c478bd9Sstevel@tonic-gate ++(cmd_info->no_of_nulled); 5090d15df17Sab196087 if (state->Sect_exists == 0) 5100d15df17Sab196087 ++state->Sect_exists; 5110d15df17Sab196087 SET_ACTION(state->sec_table[SYM].flags, ACT_DELETE); 5120d15df17Sab196087 state->off_table[SYM] = 0; 5137c478bd9Sstevel@tonic-gate /* 5147c478bd9Sstevel@tonic-gate * Can I remove section header 5157c478bd9Sstevel@tonic-gate * string table ? 5167c478bd9Sstevel@tonic-gate */ 5177c478bd9Sstevel@tonic-gate if ((tmp_shdr.sh_link < shnum) && 5187c478bd9Sstevel@tonic-gate (tmp_shdr.sh_link != SHN_UNDEF) && 5197c478bd9Sstevel@tonic-gate (tmp_shdr.sh_link != shstrndx) && 5200d15df17Sab196087 (GET_LOC(state->sec_table[tmp_shdr.sh_link].flags) == 5210d15df17Sab196087 AFTER)) { 5220d15df17Sab196087 state->sec_table[tmp_shdr.sh_link].secno = 5230d15df17Sab196087 (GElf_Word)DELETED; 5247c478bd9Sstevel@tonic-gate ++(cmd_info->no_of_nulled); 5250d15df17Sab196087 if (state->Sect_exists == 0) 5260d15df17Sab196087 ++state->Sect_exists; 5270d15df17Sab196087 SET_ACTION(state->sec_table[tmp_shdr.sh_link].flags, 5287c478bd9Sstevel@tonic-gate ACT_DELETE); 5290d15df17Sab196087 state->off_table[tmp_shdr.sh_link] = 0; 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate /* 5347c478bd9Sstevel@tonic-gate * If I only printed the contents, then 5357c478bd9Sstevel@tonic-gate * just report so. 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, pFLAG) && !CHK_OPT(cmd_info, MIGHT_CHG)) 5387c478bd9Sstevel@tonic-gate return (DONT_BUILD); /* don't bother creating a new file */ 5397c478bd9Sstevel@tonic-gate /* since the file has not changed */ 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate /* 5427c478bd9Sstevel@tonic-gate * I might need to add a new section. Check it. 5437c478bd9Sstevel@tonic-gate */ 5440d15df17Sab196087 if (state->Sect_exists == 0 && CHK_OPT(cmd_info, aFLAG)) { 5457c478bd9Sstevel@tonic-gate int act = 0; 5460d15df17Sab196087 state->new_sec_string = calloc(1, cmd_info->str_size + 1); 5470d15df17Sab196087 if (state->new_sec_string == NULL) 5487c478bd9Sstevel@tonic-gate return (FAILURE); 5497c478bd9Sstevel@tonic-gate for (act = 0; act < actmax; act++) { 5507c478bd9Sstevel@tonic-gate if (Action[act].a_action == ACT_APPEND) { 5510d15df17Sab196087 (void) strcat(state->new_sec_string, 5527c478bd9Sstevel@tonic-gate Action[act].a_string); 5530d15df17Sab196087 (void) strcat(state->new_sec_string, "\n"); 5547c478bd9Sstevel@tonic-gate cmd_info->no_of_append = 1; 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* 5607c478bd9Sstevel@tonic-gate * If I did not append any new sections, and I did not 5617c478bd9Sstevel@tonic-gate * modify/delete any sections, then just report so. 5627c478bd9Sstevel@tonic-gate */ 5630d15df17Sab196087 if ((state->Sect_exists == 0 && cmd_info->no_of_append == 0) || 5647c478bd9Sstevel@tonic-gate !CHK_OPT(cmd_info, MIGHT_CHG)) 5657c478bd9Sstevel@tonic-gate return (DONT_BUILD); 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * Found at least one section which was processed. 5697c478bd9Sstevel@tonic-gate * Deleted or Appended or Compressed. 5707c478bd9Sstevel@tonic-gate */ 5710d15df17Sab196087 if (state->Sect_exists) { 5727c478bd9Sstevel@tonic-gate /* 5737c478bd9Sstevel@tonic-gate * First, handle the deleted sections. 5747c478bd9Sstevel@tonic-gate */ 5757c478bd9Sstevel@tonic-gate if (cmd_info->no_of_delete != 0 || 5767c478bd9Sstevel@tonic-gate cmd_info->no_of_nulled != 0) { 5777c478bd9Sstevel@tonic-gate int acc = 0; 5787c478bd9Sstevel@tonic-gate int rel_idx; 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate /* 5817c478bd9Sstevel@tonic-gate * Handle relocation/target 5827c478bd9Sstevel@tonic-gate * sections. 5837c478bd9Sstevel@tonic-gate */ 5840d15df17Sab196087 sinfo = &(state->sec_table[0]); 5857c478bd9Sstevel@tonic-gate for (i = 1; i < shnum; i++) { 5867c478bd9Sstevel@tonic-gate sinfo++; 5877c478bd9Sstevel@tonic-gate rel_idx = sinfo->rel_scn_index; 5887c478bd9Sstevel@tonic-gate if (rel_idx == 0) 5897c478bd9Sstevel@tonic-gate continue; 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate /* 5927c478bd9Sstevel@tonic-gate * If I am removed, then remove my 5937c478bd9Sstevel@tonic-gate * target section. 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate if (((sinfo->secno == 5967c478bd9Sstevel@tonic-gate (GElf_Word)DELETED) || 5977c478bd9Sstevel@tonic-gate (sinfo->secno == 5987c478bd9Sstevel@tonic-gate (GElf_Word)NULLED)) && 5997c478bd9Sstevel@tonic-gate sinfo->rel_loc != IN) { 6000d15df17Sab196087 if (GET_LOC(state-> 6010d15df17Sab196087 sec_table[rel_idx].flags) == PRIOR) 6020d15df17Sab196087 state->sec_table[rel_idx]. 6030d15df17Sab196087 secno = (GElf_Word)NULLED; 6047c478bd9Sstevel@tonic-gate else 6050d15df17Sab196087 state->sec_table[rel_idx]. 6060d15df17Sab196087 secno = (GElf_Word)DELETED; 6070d15df17Sab196087 SET_ACTION(state->sec_table[rel_idx]. 6080d15df17Sab196087 flags, ACT_DELETE); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate /* 6127c478bd9Sstevel@tonic-gate * I am not removed. Check if my target is 6137c478bd9Sstevel@tonic-gate * removed or nulled. If so, let me try to 6147c478bd9Sstevel@tonic-gate * remove my self. 6157c478bd9Sstevel@tonic-gate */ 6160d15df17Sab196087 if (((state->sec_table[rel_idx].secno == 6177c478bd9Sstevel@tonic-gate (GElf_Word)DELETED) || 6180d15df17Sab196087 (state->sec_table[rel_idx].secno == 6197c478bd9Sstevel@tonic-gate (GElf_Word)NULLED)) && 6207c478bd9Sstevel@tonic-gate (GET_LOC(sinfo->flags) != IN)) { 6217c478bd9Sstevel@tonic-gate if (GET_LOC(sinfo->flags) == 6227c478bd9Sstevel@tonic-gate PRIOR) 6237c478bd9Sstevel@tonic-gate sinfo->secno = 6247c478bd9Sstevel@tonic-gate (GElf_Word)NULLED; 6257c478bd9Sstevel@tonic-gate else 6267c478bd9Sstevel@tonic-gate sinfo->secno = 6277c478bd9Sstevel@tonic-gate (GElf_Word)DELETED; 6280d15df17Sab196087 SET_ACTION(sinfo->flags, ACT_DELETE); 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate /* 6337c478bd9Sstevel@tonic-gate * Now, take care of DELETED sections 6347c478bd9Sstevel@tonic-gate */ 6350d15df17Sab196087 sinfo = &(state->sec_table[1]); 6367c478bd9Sstevel@tonic-gate for (i = 1; i < shnum; i++) { 6377c478bd9Sstevel@tonic-gate shdr = &(sinfo->shdr); 6387c478bd9Sstevel@tonic-gate if (sinfo->secno == (GElf_Word)DELETED) { 6397c478bd9Sstevel@tonic-gate acc++; 6407c478bd9Sstevel@tonic-gate /* 6410d15df17Sab196087 * The SHT_GROUP section which this 6420d15df17Sab196087 * section is a member may be able 6430d15df17Sab196087 * to be removed. See post_process(). 6447c478bd9Sstevel@tonic-gate */ 6457c478bd9Sstevel@tonic-gate if (shdr->sh_flags & SHF_GROUP) 6460d15df17Sab196087 cmd_info->flags |= 6470d15df17Sab196087 SHF_GROUP_DEL; 6487c478bd9Sstevel@tonic-gate } else { 6497c478bd9Sstevel@tonic-gate /* 6500d15df17Sab196087 * The data buffer of SHT_GROUP this 6510d15df17Sab196087 * section is a member needs to be 6520d15df17Sab196087 * updated. See post_process(). 6537c478bd9Sstevel@tonic-gate */ 6547c478bd9Sstevel@tonic-gate sinfo->secno -= acc; 6550d15df17Sab196087 if ((shdr->sh_flags & SHF_GROUP) && 6560d15df17Sab196087 (acc != 0)) 6570d15df17Sab196087 cmd_info->flags |= 6580d15df17Sab196087 SHF_GROUP_MOVE; 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate sinfo++; 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* 6667c478bd9Sstevel@tonic-gate * I know that the file has been modified. 6677c478bd9Sstevel@tonic-gate * A new file need to be created. 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate return (SUCCESS); 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate static int 6730d15df17Sab196087 build_file(Elf *src_elf, GElf_Ehdr *src_ehdr, Cmd_Info *cmd_info, 6740d15df17Sab196087 file_state_t *state) 6757c478bd9Sstevel@tonic-gate { 6767c478bd9Sstevel@tonic-gate Elf_Scn *src_scn; 6777c478bd9Sstevel@tonic-gate Elf_Scn *dst_scn; 6787c478bd9Sstevel@tonic-gate int new_sh_name = 0; /* to hold the offset for the new */ 6797c478bd9Sstevel@tonic-gate /* section's name */ 6807c478bd9Sstevel@tonic-gate Elf *dst_elf = 0; 6817c478bd9Sstevel@tonic-gate Elf_Data *elf_data; 6827c478bd9Sstevel@tonic-gate Elf_Data *data; 6837c478bd9Sstevel@tonic-gate int64_t scn_no, x; 6847c478bd9Sstevel@tonic-gate size_t no_of_symbols = 0; 6857c478bd9Sstevel@tonic-gate section_info_table *info; 6867c478bd9Sstevel@tonic-gate unsigned int c = 0; 6877c478bd9Sstevel@tonic-gate int fdtmp; 6887c478bd9Sstevel@tonic-gate GElf_Shdr src_shdr; 6897c478bd9Sstevel@tonic-gate GElf_Shdr dst_shdr; 6907c478bd9Sstevel@tonic-gate GElf_Ehdr dst_ehdr; 6917c478bd9Sstevel@tonic-gate GElf_Off new_offset = 0, r; 6927c478bd9Sstevel@tonic-gate size_t shnum, shstrndx; 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate 69562b628a6SAli Bahrami if (elf_getshdrnum(src_elf, &shnum) == -1) { 6960d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 6977c478bd9Sstevel@tonic-gate return (FAILURE); 6987c478bd9Sstevel@tonic-gate } 69962b628a6SAli Bahrami if (elf_getshdrstrndx(src_elf, &shstrndx) == -1) { 7000d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 7017c478bd9Sstevel@tonic-gate return (FAILURE); 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 704d1477c77SAli Bahrami if ((fdtmp = open(elftmpfile.tmp_name, O_RDWR | O_TRUNC | O_CREAT, 7050d15df17Sab196087 (mode_t)0666)) == -1) { 7060d15df17Sab196087 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno), 707d1477c77SAli Bahrami prog, elftmpfile.tmp_name); 7087c478bd9Sstevel@tonic-gate return (FAILURE); 7097c478bd9Sstevel@tonic-gate } 710d1477c77SAli Bahrami elftmpfile.tmp_unlink = 1; 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate if ((dst_elf = elf_begin(fdtmp, ELF_C_WRITE, (Elf *) 0)) == NULL) { 7130d15df17Sab196087 error_message(READ_ERROR, LIBelf_ERROR, elf_errmsg(-1), 714d1477c77SAli Bahrami prog, elftmpfile.tmp_name); 7157c478bd9Sstevel@tonic-gate (void) close(fdtmp); 7167c478bd9Sstevel@tonic-gate return (FAILURE); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate if (gelf_newehdr(dst_elf, gelf_getclass(src_elf)) == NULL) { 7200d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 7217c478bd9Sstevel@tonic-gate return (FAILURE); 7227c478bd9Sstevel@tonic-gate } 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate /* initialize dst_ehdr */ 7257c478bd9Sstevel@tonic-gate (void) gelf_getehdr(dst_elf, &dst_ehdr); 7267c478bd9Sstevel@tonic-gate dst_ehdr = *src_ehdr; 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate /* 7292eec250aSab196087 * If we are removing the header string table section, 7302eec250aSab196087 * remove the reference to it from the ELF header. 7312eec250aSab196087 */ 7322eec250aSab196087 if ((shstrndx != SHN_UNDEF) && 7330d15df17Sab196087 (state->sec_table[shstrndx].secno == (GElf_Word)DELETED)) 7342eec250aSab196087 dst_ehdr.e_shstrndx = SHN_UNDEF; 7352eec250aSab196087 7362eec250aSab196087 /* 7372eec250aSab196087 * flush the changes to the ehdr so the ident 7382eec250aSab196087 * array and header string table index are filled in. 7397c478bd9Sstevel@tonic-gate */ 7407c478bd9Sstevel@tonic-gate (void) gelf_update_ehdr(dst_elf, &dst_ehdr); 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate if (src_ehdr->e_phnum != 0) { 7447c478bd9Sstevel@tonic-gate (void) elf_flagelf(dst_elf, ELF_C_SET, ELF_F_LAYOUT); 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate if (gelf_newphdr(dst_elf, src_ehdr->e_phnum) == NULL) { 7470d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, 7480d15df17Sab196087 elf_errmsg(-1), prog); 7497c478bd9Sstevel@tonic-gate return (FAILURE); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate for (x = 0; x < src_ehdr->e_phnum; ++x) { 7537c478bd9Sstevel@tonic-gate GElf_Phdr dst; 7547c478bd9Sstevel@tonic-gate GElf_Phdr src; 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate /* LINTED */ 7577c478bd9Sstevel@tonic-gate (void) gelf_getphdr(src_elf, (int)x, &src); 7587c478bd9Sstevel@tonic-gate /* LINTED */ 7597c478bd9Sstevel@tonic-gate (void) gelf_getphdr(dst_elf, (int)x, &dst); 7607c478bd9Sstevel@tonic-gate (void) memcpy(&dst, &src, sizeof (GElf_Phdr)); 7617c478bd9Sstevel@tonic-gate /* LINTED */ 7627c478bd9Sstevel@tonic-gate (void) gelf_update_phdr(dst_elf, (int)x, &dst); 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7650d15df17Sab196087 x = location(dst_ehdr.e_phoff, 0, src_elf, state); 7667c478bd9Sstevel@tonic-gate if (x == AFTER) 7677c478bd9Sstevel@tonic-gate new_offset = (GElf_Off)src_ehdr->e_ehsize; 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate scn_no = 1; 7710d15df17Sab196087 while ((src_scn = state->sec_table[scn_no].scn) != (Elf_Scn *) -1) { 7720d15df17Sab196087 info = &state->sec_table[scn_no]; 7737c478bd9Sstevel@tonic-gate /* If section should be copied to new file NOW */ 7747c478bd9Sstevel@tonic-gate if ((info->secno != (GElf_Word)DELETED) && 7757c478bd9Sstevel@tonic-gate info->secno <= scn_no) { 7767c478bd9Sstevel@tonic-gate if ((dst_scn = elf_newscn(dst_elf)) == NULL) { 7777c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 7787c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 7797c478bd9Sstevel@tonic-gate return (FAILURE); 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate (void) gelf_getshdr(dst_scn, &dst_shdr); 7827c478bd9Sstevel@tonic-gate (void) gelf_getshdr(info->scn, &src_shdr); 7837c478bd9Sstevel@tonic-gate (void) memcpy(&dst_shdr, &src_shdr, sizeof (GElf_Shdr)); 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate /* 7867c478bd9Sstevel@tonic-gate * Update link and info fields 7877c478bd9Sstevel@tonic-gate * The sh_link field may have special values so 7887c478bd9Sstevel@tonic-gate * check them first. 7897c478bd9Sstevel@tonic-gate */ 7907c478bd9Sstevel@tonic-gate if ((src_shdr.sh_link >= shnum) || 7917c478bd9Sstevel@tonic-gate (src_shdr.sh_link == 0)) 7927c478bd9Sstevel@tonic-gate dst_shdr.sh_link = src_shdr.sh_link; 7930d15df17Sab196087 else if ((int)state->sec_table[src_shdr.sh_link].secno < 7940d15df17Sab196087 0) 7957c478bd9Sstevel@tonic-gate dst_shdr.sh_link = 0; 7967c478bd9Sstevel@tonic-gate else 7977c478bd9Sstevel@tonic-gate dst_shdr.sh_link = 7980d15df17Sab196087 state->sec_table[src_shdr.sh_link].secno; 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate if ((src_shdr.sh_type == SHT_REL) || 8017c478bd9Sstevel@tonic-gate (src_shdr.sh_type == SHT_RELA)) { 8027c478bd9Sstevel@tonic-gate if ((src_shdr.sh_info >= shnum) || 8030d15df17Sab196087 ((int)state->sec_table[src_shdr. 8047c478bd9Sstevel@tonic-gate sh_info].secno < 0)) 8057c478bd9Sstevel@tonic-gate dst_shdr.sh_info = 0; 8067c478bd9Sstevel@tonic-gate else 8070d15df17Sab196087 dst_shdr.sh_info = state-> 8087c478bd9Sstevel@tonic-gate sec_table[src_shdr.sh_info].secno; 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate 8110d15df17Sab196087 data = state->sec_table[scn_no].data; 8127c478bd9Sstevel@tonic-gate if ((elf_data = elf_newdata(dst_scn)) == NULL) { 8137c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 8147c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 8157c478bd9Sstevel@tonic-gate return (FAILURE); 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate *elf_data = *data; 8187c478bd9Sstevel@tonic-gate 8197a5d89c4Sab196087 /* 8207a5d89c4Sab196087 * SHT_{DYNSYM, SYMTAB} might need some change, as 8217a5d89c4Sab196087 * they may contain section symbols that reference 8227a5d89c4Sab196087 * removed sections. SHT_SUNW_LDYNSYM does not 8237a5d89c4Sab196087 * contain section symbols, and therefore does not 8247a5d89c4Sab196087 * have this issue. 8257a5d89c4Sab196087 */ 8267c478bd9Sstevel@tonic-gate if (((src_shdr.sh_type == SHT_SYMTAB) || 8277c478bd9Sstevel@tonic-gate (src_shdr.sh_type == SHT_DYNSYM)) && 8287c478bd9Sstevel@tonic-gate src_shdr.sh_entsize != 0 && 8297c478bd9Sstevel@tonic-gate (cmd_info->no_of_delete != 0 || 8307c478bd9Sstevel@tonic-gate cmd_info->no_of_nulled != 0)) { 8317c478bd9Sstevel@tonic-gate char *new_sym; 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate no_of_symbols = src_shdr.sh_size / 8347c478bd9Sstevel@tonic-gate src_shdr.sh_entsize; 8357c478bd9Sstevel@tonic-gate new_sym = malloc(no_of_symbols * 8367c478bd9Sstevel@tonic-gate src_shdr.sh_entsize); 8377c478bd9Sstevel@tonic-gate if (new_sym == NULL) { 8387c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 83957ef7aa9SRod Evans PLAIN_ERROR, NULL, prog); 8407c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate /* CSTYLED */ 8447c478bd9Sstevel@tonic-gate elf_data->d_buf = (void *) new_sym; 8457c478bd9Sstevel@tonic-gate for (c = 0; c < no_of_symbols; c++) { 8467c478bd9Sstevel@tonic-gate GElf_Sym csym; 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate (void) gelf_getsym(data, c, &csym); 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate if ((csym.st_shndx < SHN_LORESERVE) && 8517c478bd9Sstevel@tonic-gate (csym.st_shndx != SHN_UNDEF)) { 8527c478bd9Sstevel@tonic-gate section_info_table *i; 8530d15df17Sab196087 i = &state-> 8540d15df17Sab196087 sec_table[csym.st_shndx]; 8557c478bd9Sstevel@tonic-gate if (((int)i->secno != 8567c478bd9Sstevel@tonic-gate DELETED) && 8570d15df17Sab196087 ((int)i->secno != NULLED)) { 8587c478bd9Sstevel@tonic-gate csym.st_shndx = 8597c478bd9Sstevel@tonic-gate i->secno; 8600d15df17Sab196087 } else { 8610d15df17Sab196087 /* BEGIN CSTYLED */ 8627c478bd9Sstevel@tonic-gate if (src_shdr.sh_type == 8630d15df17Sab196087 SHT_SYMTAB) { 8647c478bd9Sstevel@tonic-gate /* 8657c478bd9Sstevel@tonic-gate * The section which 8667c478bd9Sstevel@tonic-gate * this * symbol relates 8677c478bd9Sstevel@tonic-gate * to is removed. 8687c478bd9Sstevel@tonic-gate * There is no way to 8697c478bd9Sstevel@tonic-gate * specify this fact, 8707c478bd9Sstevel@tonic-gate * just change the shndx 8717c478bd9Sstevel@tonic-gate * to 1. 8727c478bd9Sstevel@tonic-gate */ 8737c478bd9Sstevel@tonic-gate csym.st_shndx = 1; 8740d15df17Sab196087 } else { 8757c478bd9Sstevel@tonic-gate /* 8767c478bd9Sstevel@tonic-gate * If this is in a 8777c478bd9Sstevel@tonic-gate * .dynsym, NULL it out. 8787c478bd9Sstevel@tonic-gate */ 8797c478bd9Sstevel@tonic-gate csym.st_shndx = 0; 8807c478bd9Sstevel@tonic-gate csym.st_name = 0; 8817c478bd9Sstevel@tonic-gate csym.st_value = 0; 8827c478bd9Sstevel@tonic-gate csym.st_size = 0; 8837c478bd9Sstevel@tonic-gate csym.st_info = 0; 8847c478bd9Sstevel@tonic-gate csym.st_other = 0; 8857c478bd9Sstevel@tonic-gate csym.st_shndx = 0; 8867c478bd9Sstevel@tonic-gate } 8870d15df17Sab196087 /* END CSTYLED */ 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate (void) gelf_update_sym(elf_data, c, 8927c478bd9Sstevel@tonic-gate &csym); 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate /* update SHT_SYMTAB_SHNDX */ 8977c478bd9Sstevel@tonic-gate if ((src_shdr.sh_type == SHT_SYMTAB_SHNDX) && 8987c478bd9Sstevel@tonic-gate (src_shdr.sh_entsize != 0) && 8997c478bd9Sstevel@tonic-gate ((cmd_info->no_of_delete != 0) || 9007c478bd9Sstevel@tonic-gate (cmd_info->no_of_nulled != 0))) { 9017c478bd9Sstevel@tonic-gate GElf_Word *oldshndx; 9027c478bd9Sstevel@tonic-gate GElf_Word *newshndx; 9037c478bd9Sstevel@tonic-gate uint_t entcnt; 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate entcnt = src_shdr.sh_size / 9067c478bd9Sstevel@tonic-gate src_shdr.sh_entsize; 9077c478bd9Sstevel@tonic-gate oldshndx = data->d_buf; 9080d15df17Sab196087 newshndx = malloc(entcnt * src_shdr.sh_entsize); 9097c478bd9Sstevel@tonic-gate if (newshndx == NULL) { 9107c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 91157ef7aa9SRod Evans PLAIN_ERROR, NULL, prog); 9127c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate elf_data->d_buf = (void *)newshndx; 9157c478bd9Sstevel@tonic-gate for (c = 0; c < entcnt; c++) { 9167c478bd9Sstevel@tonic-gate if (oldshndx[c] != SHN_UNDEF) { 9177c478bd9Sstevel@tonic-gate section_info_table *i; 9180d15df17Sab196087 i = &state-> 9190d15df17Sab196087 sec_table[oldshndx[c]]; 9207c478bd9Sstevel@tonic-gate if (((int)i->secno != 9217c478bd9Sstevel@tonic-gate DELETED) && 9227c478bd9Sstevel@tonic-gate ((int)i->secno != NULLED)) 9237c478bd9Sstevel@tonic-gate newshndx[c] = i->secno; 9247c478bd9Sstevel@tonic-gate else 9257c478bd9Sstevel@tonic-gate newshndx[c] = 9267c478bd9Sstevel@tonic-gate oldshndx[c]; 9277c478bd9Sstevel@tonic-gate } else 9287c478bd9Sstevel@tonic-gate newshndx[c] = 9297c478bd9Sstevel@tonic-gate oldshndx[c]; 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate /* 9347c478bd9Sstevel@tonic-gate * If the section is to be updated, 9357c478bd9Sstevel@tonic-gate * do so. 9367c478bd9Sstevel@tonic-gate */ 9377c478bd9Sstevel@tonic-gate if (ISCANDIDATE(info->flags)) { 9387c478bd9Sstevel@tonic-gate if ((GET_LOC(info->flags) == PRIOR) && 9397c478bd9Sstevel@tonic-gate (((int)info->secno == NULLED) || 9407c478bd9Sstevel@tonic-gate ((int)info->secno == EXPANDED) || 9417c478bd9Sstevel@tonic-gate ((int)info->secno == SHRUNK))) { 9427c478bd9Sstevel@tonic-gate /* 9437c478bd9Sstevel@tonic-gate * The section is updated, 9447c478bd9Sstevel@tonic-gate * but the position is not too 9457c478bd9Sstevel@tonic-gate * good. Need to NULL this out. 9467c478bd9Sstevel@tonic-gate */ 9477c478bd9Sstevel@tonic-gate dst_shdr.sh_name = 0; 9487c478bd9Sstevel@tonic-gate dst_shdr.sh_type = SHT_PROGBITS; 9497c478bd9Sstevel@tonic-gate if ((int)info->secno != NULLED) { 9507c478bd9Sstevel@tonic-gate (cmd_info->no_of_moved)++; 9517c478bd9Sstevel@tonic-gate SET_MOVING(info->flags); 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate } else { 9547c478bd9Sstevel@tonic-gate /* 9557c478bd9Sstevel@tonic-gate * The section is positioned AFTER, 9567c478bd9Sstevel@tonic-gate * or there are no segments. 9577c478bd9Sstevel@tonic-gate * It is safe to update this section. 9587c478bd9Sstevel@tonic-gate */ 9590d15df17Sab196087 data = state->sec_table[scn_no].mdata; 9607c478bd9Sstevel@tonic-gate *elf_data = *data; 9617c478bd9Sstevel@tonic-gate dst_shdr.sh_size = elf_data->d_size; 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate /* add new section name to shstrtab? */ 9650d15df17Sab196087 else if (!state->Sect_exists && 9660d15df17Sab196087 (state->new_sec_string != NULL) && 9677c478bd9Sstevel@tonic-gate (scn_no == shstrndx) && 9687c478bd9Sstevel@tonic-gate (dst_shdr.sh_type == SHT_STRTAB) && 9697c478bd9Sstevel@tonic-gate ((src_ehdr->e_phnum == 0) || 9700d15df17Sab196087 ((x = scn_location(dst_scn, dst_elf, state)) 9710d15df17Sab196087 != IN) || 9727c478bd9Sstevel@tonic-gate (x != PRIOR))) { 9737c478bd9Sstevel@tonic-gate size_t sect_len; 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate sect_len = strlen(SECT_NAME); 9767c478bd9Sstevel@tonic-gate if ((elf_data->d_buf = 9777c478bd9Sstevel@tonic-gate malloc((dst_shdr.sh_size + 9787c478bd9Sstevel@tonic-gate sect_len + 1))) == NULL) { 9797c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 98057ef7aa9SRod Evans PLAIN_ERROR, NULL, prog); 9817c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate /* put original data plus new data in section */ 9847c478bd9Sstevel@tonic-gate (void) memcpy(elf_data->d_buf, 9857c478bd9Sstevel@tonic-gate data->d_buf, data->d_size); 9867c478bd9Sstevel@tonic-gate (void) memcpy(&((char *)elf_data->d_buf) 9870d15df17Sab196087 [data->d_size], SECT_NAME, sect_len + 1); 9887c478bd9Sstevel@tonic-gate /* LINTED */ 9897c478bd9Sstevel@tonic-gate new_sh_name = (int)dst_shdr.sh_size; 9907c478bd9Sstevel@tonic-gate dst_shdr.sh_size += sect_len + 1; 9917c478bd9Sstevel@tonic-gate elf_data->d_size += sect_len + 1; 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate /* 9957c478bd9Sstevel@tonic-gate * Compute offsets. 9967c478bd9Sstevel@tonic-gate */ 9977c478bd9Sstevel@tonic-gate if (src_ehdr->e_phnum != 0) { 9987c478bd9Sstevel@tonic-gate /* 9997c478bd9Sstevel@tonic-gate * Compute section offset. 10007c478bd9Sstevel@tonic-gate */ 10010d15df17Sab196087 if (state->off_table[scn_no] == 0) { 10027c478bd9Sstevel@tonic-gate if (dst_shdr.sh_addralign != 0) { 10037c478bd9Sstevel@tonic-gate r = new_offset % 10047c478bd9Sstevel@tonic-gate dst_shdr.sh_addralign; 10057c478bd9Sstevel@tonic-gate if (r) 10067c478bd9Sstevel@tonic-gate new_offset += 10070d15df17Sab196087 dst_shdr. 10080d15df17Sab196087 sh_addralign - r; 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate dst_shdr.sh_offset = new_offset; 10117c478bd9Sstevel@tonic-gate elf_data->d_off = 0; 10127c478bd9Sstevel@tonic-gate } else { 10130d15df17Sab196087 if (state->nobits_table[scn_no] == 0) 10140d15df17Sab196087 new_offset = 10150d15df17Sab196087 state->off_table[scn_no]; 10167c478bd9Sstevel@tonic-gate } 10170d15df17Sab196087 if (state->nobits_table[scn_no] == 0) 10187c478bd9Sstevel@tonic-gate new_offset += dst_shdr.sh_size; 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate 10212eec250aSab196087 /* flush changes */ 10222eec250aSab196087 (void) gelf_update_shdr(dst_scn, &dst_shdr); 10232eec250aSab196087 } 10247c478bd9Sstevel@tonic-gate scn_no++; 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate /* 10287c478bd9Sstevel@tonic-gate * This is the real new section. 10297c478bd9Sstevel@tonic-gate */ 10300d15df17Sab196087 if (!state->Sect_exists && state->new_sec_string != NULL) { 10317c478bd9Sstevel@tonic-gate size_t string_size; 10320d15df17Sab196087 string_size = strlen(state->new_sec_string) + 1; 10337c478bd9Sstevel@tonic-gate if ((dst_scn = elf_newscn(dst_elf)) == NULL) { 10347c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 10357c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 10367c478bd9Sstevel@tonic-gate return (FAILURE); 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate (void) gelf_getshdr(dst_scn, &dst_shdr); 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate dst_shdr.sh_name = new_sh_name; 10417c478bd9Sstevel@tonic-gate dst_shdr.sh_type = SHT_PROGBITS; 10427c478bd9Sstevel@tonic-gate dst_shdr.sh_flags = 0; 10437c478bd9Sstevel@tonic-gate dst_shdr.sh_addr = 0; 10447c478bd9Sstevel@tonic-gate if (src_ehdr->e_phnum != NULL) 10457c478bd9Sstevel@tonic-gate dst_shdr.sh_offset = new_offset; 10467c478bd9Sstevel@tonic-gate else 10477c478bd9Sstevel@tonic-gate dst_shdr.sh_offset = 0; 10487c478bd9Sstevel@tonic-gate dst_shdr.sh_size = string_size + 1; 10497c478bd9Sstevel@tonic-gate dst_shdr.sh_link = 0; 10507c478bd9Sstevel@tonic-gate dst_shdr.sh_info = 0; 10517c478bd9Sstevel@tonic-gate dst_shdr.sh_addralign = 1; 10527c478bd9Sstevel@tonic-gate dst_shdr.sh_entsize = 0; 10537c478bd9Sstevel@tonic-gate (void) gelf_update_shdr(dst_scn, &dst_shdr); /* flush changes */ 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate if ((elf_data = elf_newdata(dst_scn)) == NULL) { 10567c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 10577c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 10587c478bd9Sstevel@tonic-gate return (FAILURE); 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate elf_data->d_size = string_size + 1; 10617c478bd9Sstevel@tonic-gate if ((elf_data->d_buf = (char *) 10627c478bd9Sstevel@tonic-gate calloc(1, string_size + 1)) == NULL) { 10637c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 106457ef7aa9SRod Evans PLAIN_ERROR, NULL, prog); 10657c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate (void) memcpy(&((char *)elf_data->d_buf)[1], 10680d15df17Sab196087 state->new_sec_string, string_size); 10697c478bd9Sstevel@tonic-gate elf_data->d_align = 1; 10707c478bd9Sstevel@tonic-gate new_offset += string_size + 1; 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate /* 10747c478bd9Sstevel@tonic-gate * If there are sections which needed to be moved, 10757c478bd9Sstevel@tonic-gate * then do it here. 10767c478bd9Sstevel@tonic-gate */ 10777c478bd9Sstevel@tonic-gate if (cmd_info->no_of_moved != 0) { 10787c478bd9Sstevel@tonic-gate int cnt; 10790d15df17Sab196087 info = &state->sec_table[0]; 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < shnum; cnt++, info++) { 10827c478bd9Sstevel@tonic-gate if ((GET_MOVING(info->flags)) == 0) 10837c478bd9Sstevel@tonic-gate continue; 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate if ((src_scn = elf_getscn(src_elf, info->osecno)) == 10867c478bd9Sstevel@tonic-gate NULL) { 10877c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 10887c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 10897c478bd9Sstevel@tonic-gate return (FAILURE); 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate if (gelf_getshdr(src_scn, &src_shdr) == NULL) { 10927c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 10937c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 10947c478bd9Sstevel@tonic-gate return (FAILURE); 10957c478bd9Sstevel@tonic-gate } 10967c478bd9Sstevel@tonic-gate if ((dst_scn = elf_newscn(dst_elf)) == NULL) { 10977c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 10987c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 10997c478bd9Sstevel@tonic-gate return (FAILURE); 11007c478bd9Sstevel@tonic-gate } 11017c478bd9Sstevel@tonic-gate if (gelf_getshdr(dst_scn, &dst_shdr) == NULL) { 11027c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 11037c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 11047c478bd9Sstevel@tonic-gate return (FAILURE); 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate dst_shdr = src_shdr; 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate data = info->mdata; 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate dst_shdr.sh_offset = new_offset; /* UPDATE fields */ 11117c478bd9Sstevel@tonic-gate dst_shdr.sh_size = data->d_size; 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate if ((shnum >= src_shdr.sh_link) || 11147c478bd9Sstevel@tonic-gate (src_shdr.sh_link == 0)) 11157c478bd9Sstevel@tonic-gate dst_shdr.sh_link = src_shdr.sh_link; 11167c478bd9Sstevel@tonic-gate else 11177c478bd9Sstevel@tonic-gate dst_shdr.sh_link = 11180d15df17Sab196087 state->sec_table[src_shdr.sh_link].osecno; 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate if ((shnum >= src_shdr.sh_info) || 11217c478bd9Sstevel@tonic-gate (src_shdr.sh_info == 0)) 11227c478bd9Sstevel@tonic-gate dst_shdr.sh_info = src_shdr.sh_info; 11237c478bd9Sstevel@tonic-gate else 11247c478bd9Sstevel@tonic-gate dst_shdr.sh_info = 11250d15df17Sab196087 state->sec_table[src_shdr.sh_info].osecno; 11267c478bd9Sstevel@tonic-gate (void) gelf_update_shdr(dst_scn, &dst_shdr); 11277c478bd9Sstevel@tonic-gate if ((elf_data = elf_newdata(dst_scn)) == NULL) { 11287c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 11297c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 11307c478bd9Sstevel@tonic-gate return (FAILURE); 11317c478bd9Sstevel@tonic-gate } 11327c478bd9Sstevel@tonic-gate (void) memcpy(elf_data, data, sizeof (Elf_Data)); 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate new_offset += data->d_size; 11357c478bd9Sstevel@tonic-gate } 11367c478bd9Sstevel@tonic-gate } 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate /* 11397c478bd9Sstevel@tonic-gate * In the event that the position of the sting table has changed, 11407c478bd9Sstevel@tonic-gate * as a result of deleted sections, update the ehdr->e_shstrndx. 11417c478bd9Sstevel@tonic-gate */ 11420bc07c75Srie if ((shstrndx > 0) && (shnum > 0) && 11430d15df17Sab196087 (state->sec_table[shstrndx].secno < shnum)) { 11440d15df17Sab196087 if (state->sec_table[shstrndx].secno < SHN_LORESERVE) { 11457c478bd9Sstevel@tonic-gate dst_ehdr.e_shstrndx = 11460d15df17Sab196087 state->sec_table[dst_ehdr.e_shstrndx].secno; 11477c478bd9Sstevel@tonic-gate } else { 11487c478bd9Sstevel@tonic-gate Elf_Scn *_scn; 11497c478bd9Sstevel@tonic-gate GElf_Shdr shdr0; 11500bc07c75Srie 11517c478bd9Sstevel@tonic-gate /* 11527c478bd9Sstevel@tonic-gate * If shstrndx requires 'Extended ELF Sections' 11537c478bd9Sstevel@tonic-gate * then it is stored in shdr[0].sh_link 11547c478bd9Sstevel@tonic-gate */ 11557c478bd9Sstevel@tonic-gate dst_ehdr.e_shstrndx = SHN_XINDEX; 11567c478bd9Sstevel@tonic-gate if ((_scn = elf_getscn(dst_elf, 0)) == NULL) { 11577c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR, 11587c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog); 11597c478bd9Sstevel@tonic-gate return (FAILURE); 11607c478bd9Sstevel@tonic-gate } 11617c478bd9Sstevel@tonic-gate (void) gelf_getshdr(_scn, &shdr0); 11620d15df17Sab196087 shdr0.sh_link = state->sec_table[shstrndx].secno; 11637c478bd9Sstevel@tonic-gate (void) gelf_update_shdr(_scn, &shdr0); 11647c478bd9Sstevel@tonic-gate } 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate if (src_ehdr->e_phnum != 0) { 11687c478bd9Sstevel@tonic-gate size_t align = gelf_fsize(dst_elf, ELF_T_ADDR, 1, EV_CURRENT); 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate /* UPDATE location of program header table */ 11710d15df17Sab196087 if (location(dst_ehdr.e_phoff, 0, dst_elf, state) == AFTER) { 11727c478bd9Sstevel@tonic-gate r = new_offset % align; 11737c478bd9Sstevel@tonic-gate if (r) 11747c478bd9Sstevel@tonic-gate new_offset += align - r; 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate dst_ehdr.e_phoff = new_offset; 11770d15df17Sab196087 new_offset += dst_ehdr.e_phnum * dst_ehdr.e_phentsize; 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate /* UPDATE location of section header table */ 11800d15df17Sab196087 if ((location(dst_ehdr.e_shoff, 0, src_elf, state) == AFTER) || 11810d15df17Sab196087 ((location(dst_ehdr.e_shoff, 0, src_elf, state) == PRIOR) && 11820d15df17Sab196087 (!state->Sect_exists && state->new_sec_string != NULL))) { 11837c478bd9Sstevel@tonic-gate r = new_offset % align; 11847c478bd9Sstevel@tonic-gate if (r) 11857c478bd9Sstevel@tonic-gate new_offset += align - r; 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate dst_ehdr.e_shoff = new_offset; 11887c478bd9Sstevel@tonic-gate } 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate /* 11917c478bd9Sstevel@tonic-gate * The NOTE segment is the one segment whos 11927c478bd9Sstevel@tonic-gate * sections might get moved by mcs processing. 11937c478bd9Sstevel@tonic-gate * Make sure that the NOTE segments offset points 11947c478bd9Sstevel@tonic-gate * to the .note section. 11957c478bd9Sstevel@tonic-gate */ 11960d15df17Sab196087 if ((state->notesegndx != -1) && (state->notesctndx != -1) && 11970d15df17Sab196087 (state->sec_table[state->notesctndx].secno)) { 11987c478bd9Sstevel@tonic-gate Elf_Scn * notescn; 11997c478bd9Sstevel@tonic-gate GElf_Shdr nshdr; 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate notescn = elf_getscn(dst_elf, 12020d15df17Sab196087 state->sec_table[state->notesctndx].secno); 12037c478bd9Sstevel@tonic-gate (void) gelf_getshdr(notescn, &nshdr); 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate if (gelf_getclass(dst_elf) == ELFCLASS32) { 12067c478bd9Sstevel@tonic-gate Elf32_Phdr * ph = elf32_getphdr(dst_elf) + 12070d15df17Sab196087 state->notesegndx; 12087c478bd9Sstevel@tonic-gate /* LINTED */ 12097c478bd9Sstevel@tonic-gate ph->p_offset = (Elf32_Off)nshdr.sh_offset; 12107c478bd9Sstevel@tonic-gate } else { 12117c478bd9Sstevel@tonic-gate Elf64_Phdr * ph = elf64_getphdr(dst_elf) + 12120d15df17Sab196087 state->notesegndx; 12137c478bd9Sstevel@tonic-gate ph->p_offset = (Elf64_Off)nshdr.sh_offset; 12147c478bd9Sstevel@tonic-gate } 12157c478bd9Sstevel@tonic-gate } 12167c478bd9Sstevel@tonic-gate } 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate /* copy ehdr changes back into real ehdr */ 12197c478bd9Sstevel@tonic-gate (void) gelf_update_ehdr(dst_elf, &dst_ehdr); 12207c478bd9Sstevel@tonic-gate if (elf_update(dst_elf, ELF_C_WRITE) < 0) { 12210d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 12227c478bd9Sstevel@tonic-gate return (FAILURE); 12237c478bd9Sstevel@tonic-gate } 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate (void) elf_end(dst_elf); 12267c478bd9Sstevel@tonic-gate (void) close(fdtmp); 12277c478bd9Sstevel@tonic-gate return (SUCCESS); 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate /* 12317c478bd9Sstevel@tonic-gate * Search through PHT saving the beginning and ending segment offsets 12327c478bd9Sstevel@tonic-gate */ 12337c478bd9Sstevel@tonic-gate static int 12340d15df17Sab196087 build_segment_table(Elf * elf, GElf_Ehdr * ehdr, file_state_t *state) 12357c478bd9Sstevel@tonic-gate { 12367c478bd9Sstevel@tonic-gate unsigned int i; 12377c478bd9Sstevel@tonic-gate 12380d15df17Sab196087 state->b_e_seg_table = (Seg_Table *) 12390d15df17Sab196087 calloc(ehdr->e_phnum, sizeof (Seg_Table)); 12400d15df17Sab196087 if (state->b_e_seg_table == NULL) { 124157ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog); 12427c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate for (i = 0; i < ehdr->e_phnum; i++) { 12467c478bd9Sstevel@tonic-gate GElf_Phdr ph; 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate (void) gelf_getphdr(elf, i, &ph); 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate /* 12517c478bd9Sstevel@tonic-gate * remember the note SEGMENTS index so that we can 12527c478bd9Sstevel@tonic-gate * re-set it's p_offset later if needed. 12537c478bd9Sstevel@tonic-gate */ 12547c478bd9Sstevel@tonic-gate if (ph.p_type == PT_NOTE) 12550d15df17Sab196087 state->notesegndx = i; 12567c478bd9Sstevel@tonic-gate 12570d15df17Sab196087 state->b_e_seg_table[i].p_offset = ph.p_offset; 12580d15df17Sab196087 state->b_e_seg_table[i].p_memsz = ph.p_offset + ph.p_memsz; 12590d15df17Sab196087 state->b_e_seg_table[i].p_filesz = ph.p_offset + ph.p_filesz; 12607c478bd9Sstevel@tonic-gate } 12617c478bd9Sstevel@tonic-gate return (SUCCESS); 12627c478bd9Sstevel@tonic-gate } 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate static void 12667c478bd9Sstevel@tonic-gate copy_elf_file_to_temp_ar_file( 12677c478bd9Sstevel@tonic-gate int fdartmp, 12687c478bd9Sstevel@tonic-gate Elf_Arhdr *mem_header, 12697c478bd9Sstevel@tonic-gate char *cur_file) 12707c478bd9Sstevel@tonic-gate { 12717c478bd9Sstevel@tonic-gate char *buf; 12727c478bd9Sstevel@tonic-gate char mem_header_buf[sizeof (struct ar_hdr) + 1]; 12737c478bd9Sstevel@tonic-gate int fdtmp3; 12747c478bd9Sstevel@tonic-gate struct stat stbuf; 12757c478bd9Sstevel@tonic-gate 1276d1477c77SAli Bahrami if ((fdtmp3 = open(elftmpfile.tmp_name, O_RDONLY)) == -1) { 12770d15df17Sab196087 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno), 1278d1477c77SAli Bahrami prog, elftmpfile.tmp_name); 12797c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 12807c478bd9Sstevel@tonic-gate } 12817c478bd9Sstevel@tonic-gate 1282d1477c77SAli Bahrami (void) stat(elftmpfile.tmp_name, &stbuf); /* for size of file */ 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate if ((buf = 12857c478bd9Sstevel@tonic-gate malloc(ROUNDUP(stbuf.st_size))) == NULL) { 128657ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog); 12877c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 12887c478bd9Sstevel@tonic-gate } 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate if (read(fdtmp3, buf, stbuf.st_size) != stbuf.st_size) { 12910d15df17Sab196087 error_message(READ_MANI_ERROR, SYSTEM_ERROR, strerror(errno), 1292d1477c77SAli Bahrami prog, elftmpfile.tmp_name, cur_file); 12937c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 12947c478bd9Sstevel@tonic-gate } 12957c478bd9Sstevel@tonic-gate 12960d15df17Sab196087 (void) sprintf(mem_header_buf, FORMAT, mem_header->ar_rawname, 12970d15df17Sab196087 mem_header->ar_date, (unsigned)mem_header->ar_uid, 12980d15df17Sab196087 (unsigned)mem_header->ar_gid, (unsigned)mem_header->ar_mode, 12997c478bd9Sstevel@tonic-gate stbuf.st_size, ARFMAG); 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate if (write(fdartmp, mem_header_buf, 13027c478bd9Sstevel@tonic-gate (unsigned)sizeof (struct ar_hdr)) != 13037c478bd9Sstevel@tonic-gate (unsigned)sizeof (struct ar_hdr)) { 13040d15df17Sab196087 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, strerror(errno), 1305d1477c77SAli Bahrami prog, elftmpfile.tmp_name, cur_file); 13067c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 13077c478bd9Sstevel@tonic-gate } 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate if (stbuf.st_size & 0x1) { 13107c478bd9Sstevel@tonic-gate buf[stbuf.st_size] = '\n'; 13117c478bd9Sstevel@tonic-gate if (write(fdartmp, buf, (size_t)ROUNDUP(stbuf.st_size)) != 13127c478bd9Sstevel@tonic-gate (size_t)ROUNDUP(stbuf.st_size)) { 13130d15df17Sab196087 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, 1314d1477c77SAli Bahrami strerror(errno), prog, elftmpfile.tmp_name, 1315d1477c77SAli Bahrami cur_file); 13167c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate } else if (write(fdartmp, buf, stbuf.st_size) != stbuf.st_size) { 13190d15df17Sab196087 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, 1320d1477c77SAli Bahrami strerror(errno), prog, elftmpfile.tmp_name, 1321d1477c77SAli Bahrami cur_file); 13227c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate free(buf); 13257c478bd9Sstevel@tonic-gate (void) close(fdtmp3); 13267c478bd9Sstevel@tonic-gate } 13277c478bd9Sstevel@tonic-gate 13287c478bd9Sstevel@tonic-gate static void 13297c478bd9Sstevel@tonic-gate copy_non_elf_to_temp_ar( 13307c478bd9Sstevel@tonic-gate int fd, 13317c478bd9Sstevel@tonic-gate Elf *elf, 13327c478bd9Sstevel@tonic-gate int fdartmp, 13337c478bd9Sstevel@tonic-gate Elf_Arhdr *mem_header, 13347c478bd9Sstevel@tonic-gate char *cur_file, 13357c478bd9Sstevel@tonic-gate Cmd_Info *cmd_info) 13367c478bd9Sstevel@tonic-gate { 13377c478bd9Sstevel@tonic-gate char mem_header_buf[sizeof (struct ar_hdr) + 1]; 13387c478bd9Sstevel@tonic-gate char *file_buf; 13397c478bd9Sstevel@tonic-gate 1340*ba7866cdSAli Bahrami if ((strcmp(mem_header->ar_name, "/") != 0) && 1341*ba7866cdSAli Bahrami (strcmp(mem_header->ar_name, "/SYM64/") != 0)) { 13420d15df17Sab196087 (void) sprintf(mem_header_buf, FORMAT, mem_header->ar_rawname, 13430d15df17Sab196087 mem_header->ar_date, (unsigned)mem_header->ar_uid, 13440d15df17Sab196087 (unsigned)mem_header->ar_gid, (unsigned)mem_header->ar_mode, 13457c478bd9Sstevel@tonic-gate mem_header->ar_size, ARFMAG); 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate if (write(fdartmp, mem_header_buf, sizeof (struct ar_hdr)) != 13487c478bd9Sstevel@tonic-gate sizeof (struct ar_hdr)) { 13490d15df17Sab196087 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, 13500d15df17Sab196087 strerror(errno), prog, cur_file); 13517c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate if ((file_buf = 13547c478bd9Sstevel@tonic-gate malloc(ROUNDUP(mem_header->ar_size))) == NULL) { 135557ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, 13567c478bd9Sstevel@tonic-gate prog); 13577c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 13587c478bd9Sstevel@tonic-gate } 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate if (lseek(fd, elf_getbase(elf), 0) != elf_getbase(elf)) { 13610d15df17Sab196087 error_message(WRITE_MANI_ERROR, prog, cur_file); 13627c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate if (read(fd, file_buf, 13667c478bd9Sstevel@tonic-gate (size_t)ROUNDUP(mem_header->ar_size)) != 13677c478bd9Sstevel@tonic-gate (size_t)ROUNDUP(mem_header->ar_size)) { 13680d15df17Sab196087 error_message(READ_MANI_ERROR, SYSTEM_ERROR, 13690d15df17Sab196087 strerror(errno), prog, cur_file); 13707c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 13717c478bd9Sstevel@tonic-gate } 13727c478bd9Sstevel@tonic-gate if (write(fdartmp, 13737c478bd9Sstevel@tonic-gate file_buf, 13747c478bd9Sstevel@tonic-gate (size_t)ROUNDUP(mem_header->ar_size)) != 13757c478bd9Sstevel@tonic-gate (size_t)ROUNDUP(mem_header->ar_size)) { 13760d15df17Sab196087 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, 13770d15df17Sab196087 strerror(errno), prog, cur_file); 13787c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate free(file_buf); 13817c478bd9Sstevel@tonic-gate } else if (CHK_OPT(cmd_info, MIGHT_CHG)) { 138257ef7aa9SRod Evans error_message(SYM_TAB_AR_ERROR, PLAIN_ERROR, NULL, 13837c478bd9Sstevel@tonic-gate prog, cur_file); 138457ef7aa9SRod Evans error_message(EXEC_AR_ERROR, PLAIN_ERROR, NULL, cur_file); 13857c478bd9Sstevel@tonic-gate } 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate 1388d1477c77SAli Bahrami /* 1389d1477c77SAli Bahrami * Replace contents of file 1390d1477c77SAli Bahrami * 1391d1477c77SAli Bahrami * entry: 1392d1477c77SAli Bahrami * ofd - Open file descriptor for file fname 1393d1477c77SAli Bahrami * fname - Name of file being processed 1394d1477c77SAli Bahrami * temp_file_name - Address of pointer to temporary 1395d1477c77SAli Bahrami * file containing new contents for fname. 1396d1477c77SAli Bahrami * 1397d1477c77SAli Bahrami * exit: 1398d1477c77SAli Bahrami * The contents of the file given by temp_file->tmp_name are 1399d1477c77SAli Bahrami * copied to the file fname. The temporary file is 1400d1477c77SAli Bahrami * unlinked, and temp_file reset. 1401d1477c77SAli Bahrami */ 14027c478bd9Sstevel@tonic-gate static void 1403d1477c77SAli Bahrami copy_file(int ofd, char *fname, Tmp_File *temp_file) 14047c478bd9Sstevel@tonic-gate { 14050d15df17Sab196087 enum { MMAP_USED, MMAP_UNUSED } mmap_status; 14067c478bd9Sstevel@tonic-gate int i; 14077c478bd9Sstevel@tonic-gate int fdtmp2; 14087c478bd9Sstevel@tonic-gate struct stat stbuf; 14097c478bd9Sstevel@tonic-gate char *buf; 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate for (i = 0; signum[i]; i++) /* started writing, cannot interrupt */ 14127c478bd9Sstevel@tonic-gate (void) signal(signum[i], SIG_IGN); 14137c478bd9Sstevel@tonic-gate 1414d1477c77SAli Bahrami if ((fdtmp2 = open(temp_file->tmp_name, O_RDONLY)) == -1) { 14150d15df17Sab196087 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno), 1416d1477c77SAli Bahrami prog, temp_file->tmp_name); 14177c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 14187c478bd9Sstevel@tonic-gate } 14197c478bd9Sstevel@tonic-gate 1420d1477c77SAli Bahrami (void) stat(temp_file->tmp_name, &stbuf); /* for size of file */ 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate /* 14237c478bd9Sstevel@tonic-gate * Get the contents of the updated file. 14247c478bd9Sstevel@tonic-gate * First try mmap()'ing. If mmap() fails, 14257c478bd9Sstevel@tonic-gate * then use the malloc() and read(). 14267c478bd9Sstevel@tonic-gate */ 14270d15df17Sab196087 mmap_status = MMAP_USED; 14280d15df17Sab196087 buf = (char *)mmap(0, stbuf.st_size, PROT_READ, MAP_SHARED, fdtmp2, 0); 14290d15df17Sab196087 if (buf == (caddr_t)-1) { 14307c478bd9Sstevel@tonic-gate if ((buf = 14317c478bd9Sstevel@tonic-gate malloc(stbuf.st_size * sizeof (char))) == NULL) { 143257ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, 14337c478bd9Sstevel@tonic-gate prog); 14347c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 14357c478bd9Sstevel@tonic-gate } 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate if (read(fdtmp2, buf, stbuf.st_size) != stbuf.st_size) { 14380d15df17Sab196087 error_message(READ_SYS_ERROR, SYSTEM_ERROR, 1439d1477c77SAli Bahrami strerror(errno), prog, temp_file->tmp_name); 14407c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 14417c478bd9Sstevel@tonic-gate } 14420d15df17Sab196087 mmap_status = MMAP_UNUSED; 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate if (ftruncate(ofd, 0) == -1) { 14460d15df17Sab196087 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno), 14477c478bd9Sstevel@tonic-gate prog, fname); 14487c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate if (lseek(ofd, 0, SEEK_SET) == -1) { 14510d15df17Sab196087 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno), 14527c478bd9Sstevel@tonic-gate prog, fname); 14537c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 14547c478bd9Sstevel@tonic-gate } 14557c478bd9Sstevel@tonic-gate if ((write(ofd, buf, stbuf.st_size)) != stbuf.st_size) { 14560d15df17Sab196087 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno), 14577c478bd9Sstevel@tonic-gate prog, fname); 14587c478bd9Sstevel@tonic-gate mcs_exit(FAILURE); 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate /* 14627c478bd9Sstevel@tonic-gate * clean 14637c478bd9Sstevel@tonic-gate */ 14640d15df17Sab196087 if (mmap_status == MMAP_USED) 14657c478bd9Sstevel@tonic-gate (void) munmap(buf, stbuf.st_size); 14667c478bd9Sstevel@tonic-gate else 14677c478bd9Sstevel@tonic-gate free(buf); 14687c478bd9Sstevel@tonic-gate (void) close(fdtmp2); 1469d1477c77SAli Bahrami free_tempfile(temp_file); 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate static uint64_t 14730d15df17Sab196087 location(int64_t offset, int mem_search, Elf * elf, file_state_t *state) 14747c478bd9Sstevel@tonic-gate { 14757c478bd9Sstevel@tonic-gate int i; 14767c478bd9Sstevel@tonic-gate uint64_t upper; 14777c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr; 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate (void) gelf_getehdr(elf, &ehdr); 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate for (i = 0; i < ehdr.e_phnum; i++) { 14827c478bd9Sstevel@tonic-gate if (mem_search) 14830d15df17Sab196087 upper = state->b_e_seg_table[i].p_memsz; 14847c478bd9Sstevel@tonic-gate else 14850d15df17Sab196087 upper = state->b_e_seg_table[i].p_filesz; 14860d15df17Sab196087 if ((offset >= state->b_e_seg_table[i].p_offset) && 14877c478bd9Sstevel@tonic-gate (offset <= upper)) 14887c478bd9Sstevel@tonic-gate return (IN); 14890d15df17Sab196087 else if (offset < state->b_e_seg_table[i].p_offset) 14907c478bd9Sstevel@tonic-gate return (PRIOR); 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate return (AFTER); 14937c478bd9Sstevel@tonic-gate } 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate static uint64_t 14960d15df17Sab196087 scn_location(Elf_Scn * scn, Elf * elf, file_state_t *state) 14977c478bd9Sstevel@tonic-gate { 14987c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate (void) gelf_getshdr(scn, &shdr); 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate /* 15037c478bd9Sstevel@tonic-gate * If the section is not a NOTE section and it has no 15047c478bd9Sstevel@tonic-gate * virtual address then it is not part of a mapped segment. 15057c478bd9Sstevel@tonic-gate */ 15067c478bd9Sstevel@tonic-gate if (shdr.sh_addr == 0) 15070d15df17Sab196087 return (location(shdr.sh_offset + shdr.sh_size, 0, elf, state)); 15087c478bd9Sstevel@tonic-gate 15090d15df17Sab196087 return (location(shdr.sh_offset + shdr.sh_size, 1, elf, state)); 15107c478bd9Sstevel@tonic-gate } 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate static void 15130d15df17Sab196087 initialize(int shnum, Cmd_Info *cmd_info, file_state_t *state) 15147c478bd9Sstevel@tonic-gate { 15157c478bd9Sstevel@tonic-gate /* 15167c478bd9Sstevel@tonic-gate * Initialize command info 15177c478bd9Sstevel@tonic-gate */ 15187c478bd9Sstevel@tonic-gate cmd_info->no_of_append = cmd_info->no_of_delete = 15197c478bd9Sstevel@tonic-gate cmd_info->no_of_nulled = cmd_info->no_of_compressed = 15207c478bd9Sstevel@tonic-gate cmd_info->no_of_moved = 0; 152157ef7aa9SRod Evans cmd_info->sh_groups = NULL; 15227c478bd9Sstevel@tonic-gate 15230d15df17Sab196087 state->sec_table = (section_info_table *) 15240d15df17Sab196087 calloc(shnum + 1, sizeof (section_info_table)); 15250d15df17Sab196087 if (state->sec_table == NULL) { 152657ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog); 1527d1477c77SAli Bahrami mcs_exit(FAILURE); 15287c478bd9Sstevel@tonic-gate } 15297c478bd9Sstevel@tonic-gate 15300d15df17Sab196087 state->off_table = (int64_t *)calloc(shnum, sizeof (int64_t)); 15310d15df17Sab196087 if (state->off_table == NULL) { 153257ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog); 1533d1477c77SAli Bahrami mcs_exit(FAILURE); 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate 15360d15df17Sab196087 state->nobits_table = (int64_t *)calloc(shnum, sizeof (int64_t)); 15370d15df17Sab196087 if (state->nobits_table == NULL) { 153857ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog); 1539d1477c77SAli Bahrami mcs_exit(FAILURE); 15407c478bd9Sstevel@tonic-gate } 15417c478bd9Sstevel@tonic-gate } 15427c478bd9Sstevel@tonic-gate 15437c478bd9Sstevel@tonic-gate /* 15447c478bd9Sstevel@tonic-gate * Update the contents of SHT_GROUP if needed 15457c478bd9Sstevel@tonic-gate */ 15460d15df17Sab196087 static void 15470d15df17Sab196087 post_process(Cmd_Info *cmd_info, file_state_t *state) 15487c478bd9Sstevel@tonic-gate { 154957ef7aa9SRod Evans Aliste idx; 15507c478bd9Sstevel@tonic-gate section_info_table *sinfo; 15517c478bd9Sstevel@tonic-gate Word *grpdata, *ngrpdata; 15527c478bd9Sstevel@tonic-gate int64_t sno, sno2; 15537c478bd9Sstevel@tonic-gate Word i, j, num; 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate /* 15567c478bd9Sstevel@tonic-gate * If no change is required, then return. 15577c478bd9Sstevel@tonic-gate */ 15587c478bd9Sstevel@tonic-gate if ((cmd_info->flags & (SHF_GROUP_MOVE|SHF_GROUP_DEL)) == 0) 15597c478bd9Sstevel@tonic-gate return; 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate /* 15627c478bd9Sstevel@tonic-gate * If SHF_GROUP sections were removed, we might need to 15637c478bd9Sstevel@tonic-gate * remove SHT_GROUP sections. 15647c478bd9Sstevel@tonic-gate */ 15657c478bd9Sstevel@tonic-gate if (cmd_info->flags & SHF_GROUP_DEL) { 15667c478bd9Sstevel@tonic-gate Word grpcnt; 15677c478bd9Sstevel@tonic-gate int deleted = 0; 15687c478bd9Sstevel@tonic-gate 156957ef7aa9SRod Evans for (APLIST_TRAVERSE(cmd_info->sh_groups, idx, sinfo)) { 15707c478bd9Sstevel@tonic-gate if (sinfo->secno == (GElf_Word)DELETED) 15717c478bd9Sstevel@tonic-gate continue; 15727c478bd9Sstevel@tonic-gate num = (sinfo->shdr).sh_size/sizeof (Word); 15737c478bd9Sstevel@tonic-gate grpcnt = 0; 15747c478bd9Sstevel@tonic-gate grpdata = (Word *)(sinfo->data->d_buf); 15757c478bd9Sstevel@tonic-gate for (i = 1; i < num; i++) { 15760d15df17Sab196087 if (state->sec_table[grpdata[i]].secno != 15775aefb655Srie (GElf_Word)DELETED) 15787c478bd9Sstevel@tonic-gate grpcnt++; 15797c478bd9Sstevel@tonic-gate } 15807c478bd9Sstevel@tonic-gate 15817c478bd9Sstevel@tonic-gate /* 15827c478bd9Sstevel@tonic-gate * All members in this SHT_GROUP were removed. 15837c478bd9Sstevel@tonic-gate * We can remove this SHT_GROUP. 15847c478bd9Sstevel@tonic-gate */ 15857c478bd9Sstevel@tonic-gate if (grpcnt == 0) { 15867c478bd9Sstevel@tonic-gate sinfo->secno = (GElf_Word)DELETED; 15877c478bd9Sstevel@tonic-gate (cmd_info->no_of_delete)++; 15887c478bd9Sstevel@tonic-gate deleted = 1; 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate } 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate /* 15937c478bd9Sstevel@tonic-gate * If we deleted a SHT_GROUP section, 15947c478bd9Sstevel@tonic-gate * we need to reasign section numbers. 15957c478bd9Sstevel@tonic-gate */ 15967c478bd9Sstevel@tonic-gate if (deleted) { 15977c478bd9Sstevel@tonic-gate section_info_table *sinfo; 15987c478bd9Sstevel@tonic-gate 15997c478bd9Sstevel@tonic-gate sno = 1; 16007c478bd9Sstevel@tonic-gate sno2 = 1; 16010d15df17Sab196087 while (state->sec_table[sno].scn != (Elf_Scn *)-1) { 16020d15df17Sab196087 sinfo = &state->sec_table[sno]; 16037c478bd9Sstevel@tonic-gate if (sinfo->secno != (GElf_Word) DELETED) 16047c478bd9Sstevel@tonic-gate sinfo->secno = sno2++; 16057c478bd9Sstevel@tonic-gate sno++; 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate } 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate /* 161157ef7aa9SRod Evans * Now we can update data buffers of the SHT_GROUP sections. 16127c478bd9Sstevel@tonic-gate */ 161357ef7aa9SRod Evans for (APLIST_TRAVERSE(cmd_info->sh_groups, idx, sinfo)) { 16147c478bd9Sstevel@tonic-gate if (sinfo->secno == (GElf_Word)DELETED) 16157c478bd9Sstevel@tonic-gate continue; 16167c478bd9Sstevel@tonic-gate num = (sinfo->shdr).sh_size/sizeof (Word); 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate /* 16197c478bd9Sstevel@tonic-gate * Need to generate the updated data buffer 16207c478bd9Sstevel@tonic-gate */ 16217c478bd9Sstevel@tonic-gate if ((sinfo->mdata = malloc(sizeof (Elf_Data))) == NULL) { 162257ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, 16237c478bd9Sstevel@tonic-gate prog); 1624d1477c77SAli Bahrami mcs_exit(FAILURE); 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate *(sinfo->mdata) = *(sinfo->data); 16277c478bd9Sstevel@tonic-gate if ((ngrpdata = sinfo->mdata->d_buf = 16287c478bd9Sstevel@tonic-gate malloc(sinfo->data->d_size)) == NULL) { 162957ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, 16307c478bd9Sstevel@tonic-gate prog); 1631d1477c77SAli Bahrami mcs_exit(FAILURE); 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate grpdata = (Word *)(sinfo->data->d_buf); 16357c478bd9Sstevel@tonic-gate ngrpdata[0] = grpdata[0]; 16367c478bd9Sstevel@tonic-gate j = 1; 16377c478bd9Sstevel@tonic-gate for (i = 1; i < num; i++) { 16380d15df17Sab196087 if (state->sec_table[grpdata[i]].secno != 16390d15df17Sab196087 (GElf_Word)DELETED) { 16400d15df17Sab196087 ngrpdata[j++] = 16410d15df17Sab196087 state->sec_table[grpdata[i]].secno; 16427c478bd9Sstevel@tonic-gate } 16437c478bd9Sstevel@tonic-gate } 16447c478bd9Sstevel@tonic-gate sinfo->mdata->d_size = j * sizeof (Word); 16457c478bd9Sstevel@tonic-gate sinfo->data = sinfo->mdata; 16467c478bd9Sstevel@tonic-gate } 164757ef7aa9SRod Evans free(cmd_info->sh_groups); 164857ef7aa9SRod Evans cmd_info->sh_groups = NULL; 16497c478bd9Sstevel@tonic-gate } 1650