xref: /titanic_50/usr/src/cmd/sgs/mcs/common/file.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
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
each_file(char * cur_file,Cmd_Info * cmd_info)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
process_file(Elf * elf,char * cur_file,Cmd_Info * cmd_info)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
traverse_file(Elf * elf,GElf_Ehdr * ehdr,char * cur_file,Cmd_Info * cmd_info,file_state_t * state)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
build_file(Elf * src_elf,GElf_Ehdr * src_ehdr,Cmd_Info * cmd_info,file_state_t * state)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
build_segment_table(Elf * elf,GElf_Ehdr * ehdr,file_state_t * state)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
copy_elf_file_to_temp_ar_file(int fdartmp,Elf_Arhdr * mem_header,char * cur_file)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
copy_non_elf_to_temp_ar(int fd,Elf * elf,int fdartmp,Elf_Arhdr * mem_header,char * cur_file,Cmd_Info * cmd_info)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
copy_file(int ofd,char * fname,Tmp_File * temp_file)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
location(int64_t offset,int mem_search,Elf * elf,file_state_t * state)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
scn_location(Elf_Scn * scn,Elf * elf,file_state_t * state)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
initialize(int shnum,Cmd_Info * cmd_info,file_state_t * state)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
post_process(Cmd_Info * cmd_info,file_state_t * state)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