xref: /illumos-gate/usr/src/cmd/sgs/mcs/common/utils.c (revision 56b75c05)
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
50d15df17Sab  * Common Development and Distribution License (the "License").
60d15df17Sab  * 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  */
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate  *	Copyright(c) 1988 AT&T
237c478bd9Sstevel@tonic-gate  *	  All Rights Reserved
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
2857ef7aa9SRod Evans  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
297c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
307c478bd9Sstevel@tonic-gate  */
31*56b75c05SAndy Fiddaman /*
32*56b75c05SAndy Fiddaman  * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
33*56b75c05SAndy Fiddaman  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include "mcs.h"
367c478bd9Sstevel@tonic-gate #include "extern.h"
377c478bd9Sstevel@tonic-gate #include "gelf.h"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * Function prototypes.
417c478bd9Sstevel@tonic-gate  */
427c478bd9Sstevel@tonic-gate static void docompress(section_info_table *);
437c478bd9Sstevel@tonic-gate static char *compress(char *, size_t *);
447c478bd9Sstevel@tonic-gate static void doappend(char *, section_info_table *);
457c478bd9Sstevel@tonic-gate static void doprint(char *, section_info_table *);
467c478bd9Sstevel@tonic-gate static void dozap(section_info_table *);
477c478bd9Sstevel@tonic-gate static int dohash(char *);
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /*
527c478bd9Sstevel@tonic-gate  * Apply the actions specified by the user.
537c478bd9Sstevel@tonic-gate  */
547c478bd9Sstevel@tonic-gate int
apply_action(section_info_table * info,char * cur_file,Cmd_Info * cmd_info)557c478bd9Sstevel@tonic-gate apply_action(section_info_table *info, char *cur_file, Cmd_Info *cmd_info)
567c478bd9Sstevel@tonic-gate {
577c478bd9Sstevel@tonic-gate 	int act_index;
587c478bd9Sstevel@tonic-gate 	int ret = 0;
597c478bd9Sstevel@tonic-gate 	GElf_Shdr shdr;
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate 	(void) gelf_getshdr(info->scn, &shdr);
627c478bd9Sstevel@tonic-gate 	for (act_index = 0; act_index < actmax; act_index++) {
637c478bd9Sstevel@tonic-gate 		Action[act_index].a_cnt++;
647c478bd9Sstevel@tonic-gate 		switch (Action[act_index].a_action) {
657c478bd9Sstevel@tonic-gate 		case ACT_ZAP:
66*56b75c05SAndy Fiddaman 			if (GET_ACTION(info->si_flags) == ACT_DELETE)
677c478bd9Sstevel@tonic-gate 				break;
687c478bd9Sstevel@tonic-gate 			dozap(info);
69*56b75c05SAndy Fiddaman 			SET_ACTION(info->si_flags, ACT_ZAP);
70*56b75c05SAndy Fiddaman 			SET_MODIFIED(info->si_flags);
717c478bd9Sstevel@tonic-gate 			break;
727c478bd9Sstevel@tonic-gate 		case ACT_PRINT:
73*56b75c05SAndy Fiddaman 			if (GET_ACTION(info->si_flags) == ACT_DELETE)
747c478bd9Sstevel@tonic-gate 				break;
757c478bd9Sstevel@tonic-gate 			if (shdr.sh_type == SHT_NOBITS) {
760d15df17Sab 				error_message(ACT_PRINT_ERROR, PLAIN_ERROR,
7757ef7aa9SRod Evans 				    NULL, prog, cur_file, SECT_NAME);
787c478bd9Sstevel@tonic-gate 				break;
797c478bd9Sstevel@tonic-gate 			}
807c478bd9Sstevel@tonic-gate 			doprint(cur_file, info);
817c478bd9Sstevel@tonic-gate 			break;
827c478bd9Sstevel@tonic-gate 		case ACT_DELETE:
837c478bd9Sstevel@tonic-gate 			/*
847c478bd9Sstevel@tonic-gate 			 * If I am strip command, this is the
857c478bd9Sstevel@tonic-gate 			 * only action I can take.
867c478bd9Sstevel@tonic-gate 			 */
87*56b75c05SAndy Fiddaman 			if (GET_ACTION(info->si_flags) == ACT_DELETE)
887c478bd9Sstevel@tonic-gate 				break;
89*56b75c05SAndy Fiddaman 			if (GET_LOC(info->si_flags) == IN) {
907c478bd9Sstevel@tonic-gate 				/*
917c478bd9Sstevel@tonic-gate 				 * If I am 'strip', I have to
927c478bd9Sstevel@tonic-gate 				 * unset the candidate flag and
937c478bd9Sstevel@tonic-gate 				 * unset the error return code.
947c478bd9Sstevel@tonic-gate 				 */
95*56b75c05SAndy Fiddaman 				if (CHK_OPT(cmd_info, I_AM_STRIP)) {
967c478bd9Sstevel@tonic-gate 					ret = 0;
97*56b75c05SAndy Fiddaman 					UNSET_CANDIDATE(info->si_flags);
987c478bd9Sstevel@tonic-gate 				} else {
990d15df17Sab 					char *name = info->name;
1000d15df17Sab 
1017c478bd9Sstevel@tonic-gate 					ret++;
1020d15df17Sab 					if (name == NULL)
1030d15df17Sab 						name = gettext("<unknown>");
1047c478bd9Sstevel@tonic-gate 					error_message(ACT_DELETE1_ERROR,
10557ef7aa9SRod Evans 					    PLAIN_ERROR, NULL,
1060d15df17Sab 					    prog, cur_file, name);
1077c478bd9Sstevel@tonic-gate 				}
1087c478bd9Sstevel@tonic-gate 				break;
1097c478bd9Sstevel@tonic-gate 			} else if (info->rel_loc == IN) {
1107c478bd9Sstevel@tonic-gate 				/*
1117c478bd9Sstevel@tonic-gate 				 * If I am 'strip', I have to
1127c478bd9Sstevel@tonic-gate 				 * unset the candidate flag and
1137c478bd9Sstevel@tonic-gate 				 * unset the error return code.
1147c478bd9Sstevel@tonic-gate 				 */
115*56b75c05SAndy Fiddaman 				if (CHK_OPT(cmd_info, I_AM_STRIP)) {
1167c478bd9Sstevel@tonic-gate 					ret = 0;
117*56b75c05SAndy Fiddaman 					UNSET_CANDIDATE(info->si_flags);
1187c478bd9Sstevel@tonic-gate 				} else {
1197c478bd9Sstevel@tonic-gate 					ret++;
1207c478bd9Sstevel@tonic-gate 					error_message(ACT_DELETE2_ERROR,
12157ef7aa9SRod Evans 					    PLAIN_ERROR, NULL,
1220d15df17Sab 					    prog, cur_file, SECT_NAME,
1230d15df17Sab 					    info->rel_name);
1247c478bd9Sstevel@tonic-gate 				}
1257c478bd9Sstevel@tonic-gate 				break;
126*56b75c05SAndy Fiddaman 			} else if (GET_LOC(info->si_flags) == PRIOR) {
1277c478bd9Sstevel@tonic-gate 				/*
1287c478bd9Sstevel@tonic-gate 				 * I can not delete this
1297c478bd9Sstevel@tonic-gate 				 * section. I can only NULL
1307c478bd9Sstevel@tonic-gate 				 * this out.
1317c478bd9Sstevel@tonic-gate 				 */
1327c478bd9Sstevel@tonic-gate 				info->secno = (GElf_Word)NULLED;
1337c478bd9Sstevel@tonic-gate 				(cmd_info->no_of_nulled)++;
1347c478bd9Sstevel@tonic-gate 			} else {
1357c478bd9Sstevel@tonic-gate 				info->secno = (GElf_Word)DELETED;
1367c478bd9Sstevel@tonic-gate 				(cmd_info->no_of_delete)++;
1377c478bd9Sstevel@tonic-gate 			}
138*56b75c05SAndy Fiddaman 			SET_ACTION(info->si_flags, ACT_DELETE);
139*56b75c05SAndy Fiddaman 			SET_MODIFIED(info->si_flags);
1407c478bd9Sstevel@tonic-gate 			break;
1417c478bd9Sstevel@tonic-gate 		case ACT_APPEND:
1427c478bd9Sstevel@tonic-gate 			if (shdr.sh_type == SHT_NOBITS) {
1437c478bd9Sstevel@tonic-gate 				ret++;
14457ef7aa9SRod Evans 				error_message(ACT_APPEND1_ERROR, PLAIN_ERROR,
14557ef7aa9SRod Evans 				    NULL, prog, cur_file, SECT_NAME);
1467c478bd9Sstevel@tonic-gate 				break;
147*56b75c05SAndy Fiddaman 			} else if (GET_LOC(info->si_flags) == IN) {
1487c478bd9Sstevel@tonic-gate 				ret++;
14957ef7aa9SRod Evans 				error_message(ACT_APPEND2_ERROR, PLAIN_ERROR,
15057ef7aa9SRod Evans 				    NULL, prog, cur_file, SECT_NAME);
1517c478bd9Sstevel@tonic-gate 				break;
1527c478bd9Sstevel@tonic-gate 			}
1537c478bd9Sstevel@tonic-gate 			doappend(Action[act_index].a_string, info);
1547c478bd9Sstevel@tonic-gate 			(cmd_info->no_of_append)++;
1557c478bd9Sstevel@tonic-gate 			info->secno = info->osecno;
156*56b75c05SAndy Fiddaman 			SET_ACTION(info->si_flags, ACT_APPEND);
157*56b75c05SAndy Fiddaman 			SET_MODIFIED(info->si_flags);
158*56b75c05SAndy Fiddaman 			if (GET_LOC(info->si_flags) == PRIOR)
1597c478bd9Sstevel@tonic-gate 				info->secno = (GElf_Word)EXPANDED;
1607c478bd9Sstevel@tonic-gate 			break;
1617c478bd9Sstevel@tonic-gate 		case ACT_COMPRESS:
1627c478bd9Sstevel@tonic-gate 			/*
1637c478bd9Sstevel@tonic-gate 			 * If this section is already deleted,
1647c478bd9Sstevel@tonic-gate 			 * don't do anything.
1657c478bd9Sstevel@tonic-gate 			 */
166*56b75c05SAndy Fiddaman 			if (GET_ACTION(info->si_flags) == ACT_DELETE)
1677c478bd9Sstevel@tonic-gate 				break;
1687c478bd9Sstevel@tonic-gate 			if (shdr.sh_type == SHT_NOBITS) {
1697c478bd9Sstevel@tonic-gate 				ret++;
17057ef7aa9SRod Evans 				error_message(ACT_COMPRESS1_ERROR, PLAIN_ERROR,
17157ef7aa9SRod Evans 				    NULL, prog, cur_file, SECT_NAME);
1727c478bd9Sstevel@tonic-gate 				break;
173*56b75c05SAndy Fiddaman 			} else if (GET_LOC(info->si_flags) == IN) {
1747c478bd9Sstevel@tonic-gate 				ret++;
17557ef7aa9SRod Evans 				error_message(ACT_COMPRESS2_ERROR, PLAIN_ERROR,
17657ef7aa9SRod Evans 				    NULL, prog, cur_file, SECT_NAME);
1777c478bd9Sstevel@tonic-gate 				break;
1787c478bd9Sstevel@tonic-gate 			}
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 			docompress(info);
1817c478bd9Sstevel@tonic-gate 			(cmd_info->no_of_compressed)++;
182*56b75c05SAndy Fiddaman 			SET_ACTION(info->si_flags, ACT_COMPRESS);
183*56b75c05SAndy Fiddaman 			SET_MODIFIED(info->si_flags);
184*56b75c05SAndy Fiddaman 			if (GET_LOC(info->si_flags) == PRIOR)
1857c478bd9Sstevel@tonic-gate 				info->secno = (GElf_Word)SHRUNK;
1867c478bd9Sstevel@tonic-gate 			break;
1877c478bd9Sstevel@tonic-gate 		}
1887c478bd9Sstevel@tonic-gate 	}
1897c478bd9Sstevel@tonic-gate 	return (ret);
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate /*
1937c478bd9Sstevel@tonic-gate  * ACT_ZAP
1947c478bd9Sstevel@tonic-gate  */
1957c478bd9Sstevel@tonic-gate static void
dozap(section_info_table * info)1967c478bd9Sstevel@tonic-gate dozap(section_info_table *info)
1977c478bd9Sstevel@tonic-gate {
1987c478bd9Sstevel@tonic-gate 	Elf_Data *data;
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	info->mdata = data = malloc(sizeof (Elf_Data));
2017c478bd9Sstevel@tonic-gate 	if (data == NULL) {
20257ef7aa9SRod Evans 		error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
203d1477c77SAli Bahrami 		mcs_exit(FAILURE);
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 	*data = *info->data;
2067c478bd9Sstevel@tonic-gate 	data->d_buf = calloc(1, data->d_size);
2077c478bd9Sstevel@tonic-gate 	if (data->d_buf == NULL) {
20857ef7aa9SRod Evans 		error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
209d1477c77SAli Bahrami 		mcs_exit(FAILURE);
2107c478bd9Sstevel@tonic-gate 	}
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate  * ACT_PRINT
2157c478bd9Sstevel@tonic-gate  */
2167c478bd9Sstevel@tonic-gate static void
doprint(char * cur_file,section_info_table * info)2177c478bd9Sstevel@tonic-gate doprint(char *cur_file, section_info_table *info)
2187c478bd9Sstevel@tonic-gate {
2197c478bd9Sstevel@tonic-gate 	Elf_Data *data;
2207c478bd9Sstevel@tonic-gate 	size_t	temp_size;
2217c478bd9Sstevel@tonic-gate 	char	*temp_string;
2227c478bd9Sstevel@tonic-gate 
223*56b75c05SAndy Fiddaman 	if (GET_MODIFIED(info->si_flags) == 0)
2247c478bd9Sstevel@tonic-gate 		data = info->data;
2257c478bd9Sstevel@tonic-gate 	else
2267c478bd9Sstevel@tonic-gate 		data = info->mdata;
2277c478bd9Sstevel@tonic-gate 	if (data == 0)
2287c478bd9Sstevel@tonic-gate 		return;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	temp_size = data->d_size;
2317c478bd9Sstevel@tonic-gate 	temp_string = data->d_buf;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (temp_size == 0)
2347c478bd9Sstevel@tonic-gate 		return;
2357c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "%s:\n", cur_file);
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	while (temp_size--) {
2387c478bd9Sstevel@tonic-gate 		char c = *temp_string++;
2397c478bd9Sstevel@tonic-gate 		switch (c) {
2407c478bd9Sstevel@tonic-gate 		case '\0':
2417c478bd9Sstevel@tonic-gate 			(void) putchar('\n');
2427c478bd9Sstevel@tonic-gate 			break;
2437c478bd9Sstevel@tonic-gate 		default:
2447c478bd9Sstevel@tonic-gate 			(void) putchar(c);
2457c478bd9Sstevel@tonic-gate 			break;
2467c478bd9Sstevel@tonic-gate 		}
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 	(void) putchar('\n');
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate /*
2527c478bd9Sstevel@tonic-gate  * ACT_APPEND
2537c478bd9Sstevel@tonic-gate  */
2547c478bd9Sstevel@tonic-gate static void
doappend(char * a_string,section_info_table * info)2557c478bd9Sstevel@tonic-gate doappend(char *a_string, section_info_table *info)
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate 	Elf_Data *data;
2587c478bd9Sstevel@tonic-gate 	char *p;
2597c478bd9Sstevel@tonic-gate 	size_t len;
2607c478bd9Sstevel@tonic-gate 	char *tp;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	/*
263835cdddcSab 	 * Get the length of the string to be added. We accept any
264835cdddcSab 	 * string (even null), as this is arbitrary user defined text.
265835cdddcSab 	 *
266835cdddcSab 	 * The caller expects this routine to replace a NULL info->mdata
267835cdddcSab 	 * field with a pointer to a freshly allocated copy. Any attempt
268835cdddcSab 	 * to optimize away a null string append would have to deal with
269835cdddcSab 	 * that, as failing to do so will cause a segfault when the NULL
270835cdddcSab 	 * mdata field is dereferenced. Accepting null strings in
271835cdddcSab 	 * this very unimportant case eliminates the need for that.
2727c478bd9Sstevel@tonic-gate 	 */
2737c478bd9Sstevel@tonic-gate 	len = strlen(a_string);
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	/*
2767c478bd9Sstevel@tonic-gate 	 * Every modification operation will be done
2777c478bd9Sstevel@tonic-gate 	 * to a new Elf_Data descriptor.
2787c478bd9Sstevel@tonic-gate 	 */
2797c478bd9Sstevel@tonic-gate 	if (info->mdata == 0) {
2807c478bd9Sstevel@tonic-gate 		/*
2817c478bd9Sstevel@tonic-gate 		 * mdata is not allocated yet.
2827c478bd9Sstevel@tonic-gate 		 * Allocate the data and set it.
2837c478bd9Sstevel@tonic-gate 		 */
2847c478bd9Sstevel@tonic-gate 		info->mdata = data = calloc(1, sizeof (Elf_Data));
2857c478bd9Sstevel@tonic-gate 		if (data == NULL) {
28657ef7aa9SRod Evans 			error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
287d1477c77SAli Bahrami 			mcs_exit(FAILURE);
2887c478bd9Sstevel@tonic-gate 		}
2897c478bd9Sstevel@tonic-gate 		*data = *info->data;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 		/*
2927c478bd9Sstevel@tonic-gate 		 * Check if the section is deleted or not.
2937c478bd9Sstevel@tonic-gate 		 * Or if the size is 0 or not.
2947c478bd9Sstevel@tonic-gate 		 */
295*56b75c05SAndy Fiddaman 		if ((GET_ACTION(info->si_flags) == ACT_DELETE) ||
2967c478bd9Sstevel@tonic-gate 		    data->d_size == 0) {
2977c478bd9Sstevel@tonic-gate 			/*
2987c478bd9Sstevel@tonic-gate 			 * The section was deleated.
2997c478bd9Sstevel@tonic-gate 			 * But now, the user wants to add data to this
3007c478bd9Sstevel@tonic-gate 			 * section.
3017c478bd9Sstevel@tonic-gate 			 */
3027c478bd9Sstevel@tonic-gate 			data->d_buf = calloc(1, len + 2);
30357ef7aa9SRod Evans 			if (data->d_buf == NULL) {
30457ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
30557ef7aa9SRod Evans 				    prog);
306d1477c77SAli Bahrami 				mcs_exit(FAILURE);
3077c478bd9Sstevel@tonic-gate 			}
3087c478bd9Sstevel@tonic-gate 			tp = (char *)data->d_buf;
3097c478bd9Sstevel@tonic-gate 			(void) memcpy(& tp[1], a_string, len + 1);
3107c478bd9Sstevel@tonic-gate 			data->d_size = len + 2;
3117c478bd9Sstevel@tonic-gate 		} else {
3127c478bd9Sstevel@tonic-gate 			/*
3137c478bd9Sstevel@tonic-gate 			 * The user wants to add data to the section.
3147c478bd9Sstevel@tonic-gate 			 * I am not going to change the original data.
3157c478bd9Sstevel@tonic-gate 			 * Do the modification on the new one.
3167c478bd9Sstevel@tonic-gate 			 */
3177c478bd9Sstevel@tonic-gate 			p = malloc(len + 1 + data->d_size);
3187c478bd9Sstevel@tonic-gate 			if (p == NULL) {
31957ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
32057ef7aa9SRod Evans 				    prog);
321d1477c77SAli Bahrami 				mcs_exit(FAILURE);
3227c478bd9Sstevel@tonic-gate 			}
3237c478bd9Sstevel@tonic-gate 			(void) memcpy(p, data->d_buf, data->d_size);
3247c478bd9Sstevel@tonic-gate 			(void) memcpy(&p[data->d_size], a_string, len + 1);
3257c478bd9Sstevel@tonic-gate 			data->d_buf = p;
3267c478bd9Sstevel@tonic-gate 			data->d_size = data->d_size + len + 1;
3277c478bd9Sstevel@tonic-gate 		}
3287c478bd9Sstevel@tonic-gate 	} else {
3297c478bd9Sstevel@tonic-gate 		/*
3307c478bd9Sstevel@tonic-gate 		 * mdata is already allocated.
3317c478bd9Sstevel@tonic-gate 		 * Modify it.
3327c478bd9Sstevel@tonic-gate 		 */
3337c478bd9Sstevel@tonic-gate 		data = info->mdata;
334*56b75c05SAndy Fiddaman 		if ((GET_ACTION(info->si_flags) == ACT_DELETE) ||
3357c478bd9Sstevel@tonic-gate 		    data->d_size == 0) {
3367c478bd9Sstevel@tonic-gate 			/*
3377c478bd9Sstevel@tonic-gate 			 * The section was deleated.
3387c478bd9Sstevel@tonic-gate 			 * But now, the user wants to add data to this
3397c478bd9Sstevel@tonic-gate 			 * section.
3407c478bd9Sstevel@tonic-gate 			 */
3417c478bd9Sstevel@tonic-gate 			if (data->d_buf)
3427c478bd9Sstevel@tonic-gate 				free(data->d_buf);
3437c478bd9Sstevel@tonic-gate 			data->d_buf = calloc(1, len + 2);
34457ef7aa9SRod Evans 			if (data->d_buf == NULL) {
34557ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
34657ef7aa9SRod Evans 				    prog);
347d1477c77SAli Bahrami 				mcs_exit(FAILURE);
3487c478bd9Sstevel@tonic-gate 			}
3497c478bd9Sstevel@tonic-gate 			tp = (char *)data->d_buf;
3507c478bd9Sstevel@tonic-gate 			(void) memcpy(&tp[1], a_string, len + 1);
3517c478bd9Sstevel@tonic-gate 			data->d_size = len + 2;
3527c478bd9Sstevel@tonic-gate 		} else {
3537c478bd9Sstevel@tonic-gate 			/*
3547c478bd9Sstevel@tonic-gate 			 * The user wants to add data to the section.
3557c478bd9Sstevel@tonic-gate 			 * I am not going to change the original data.
3567c478bd9Sstevel@tonic-gate 			 * Do the modification on the new one.
3577c478bd9Sstevel@tonic-gate 			 */
3587c478bd9Sstevel@tonic-gate 			p = malloc(len + 1 + data->d_size);
3597c478bd9Sstevel@tonic-gate 			if (p == NULL) {
36057ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
36157ef7aa9SRod Evans 				    prog);
362d1477c77SAli Bahrami 				mcs_exit(FAILURE);
3637c478bd9Sstevel@tonic-gate 			}
3647c478bd9Sstevel@tonic-gate 			(void) memcpy(p, data->d_buf, data->d_size);
3657c478bd9Sstevel@tonic-gate 			(void) memcpy(&p[data->d_size], a_string, len + 1);
3667c478bd9Sstevel@tonic-gate 			free(data->d_buf);
3677c478bd9Sstevel@tonic-gate 			data->d_buf = p;
3687c478bd9Sstevel@tonic-gate 			data->d_size = data->d_size + len + 1;
3697c478bd9Sstevel@tonic-gate 		}
3707c478bd9Sstevel@tonic-gate 	}
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate /*
3747c478bd9Sstevel@tonic-gate  * ACT_COMPRESS
3757c478bd9Sstevel@tonic-gate  */
3767c478bd9Sstevel@tonic-gate #define	HALFLONG 16
3777c478bd9Sstevel@tonic-gate #define	low(x)  (x&((1L<<HALFLONG)-1))
3787c478bd9Sstevel@tonic-gate #define	high(x) (x>>HALFLONG)
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate static void
docompress(section_info_table * info)3817c478bd9Sstevel@tonic-gate docompress(section_info_table *info)
3827c478bd9Sstevel@tonic-gate {
3837c478bd9Sstevel@tonic-gate 	Elf_Data *data;
3847c478bd9Sstevel@tonic-gate 	size_t size;
3857c478bd9Sstevel@tonic-gate 	char *buf;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	if (info->mdata == 0) {
3887c478bd9Sstevel@tonic-gate 		/*
3897c478bd9Sstevel@tonic-gate 		 * mdata is not allocated yet.
3907c478bd9Sstevel@tonic-gate 		 * Allocate the data and set it.
3917c478bd9Sstevel@tonic-gate 		 */
3927c478bd9Sstevel@tonic-gate 		char *p;
3937c478bd9Sstevel@tonic-gate 		info->mdata = data = calloc(1, sizeof (Elf_Data));
3947c478bd9Sstevel@tonic-gate 		if (data == NULL) {
39557ef7aa9SRod Evans 			error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
396d1477c77SAli Bahrami 			mcs_exit(FAILURE);
3977c478bd9Sstevel@tonic-gate 		}
3987c478bd9Sstevel@tonic-gate 		*data = *info->data;
3997c478bd9Sstevel@tonic-gate 		p = malloc(data->d_size);
4007c478bd9Sstevel@tonic-gate 		(void) memcpy(p, (char *)data->d_buf, data->d_size);
4017c478bd9Sstevel@tonic-gate 		data->d_buf = p;
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 	size = info->mdata->d_size;
4047c478bd9Sstevel@tonic-gate 	buf = (char *)info->mdata->d_buf;
4057c478bd9Sstevel@tonic-gate 	buf = compress(buf, &size);
4067c478bd9Sstevel@tonic-gate 	info->mdata->d_buf = buf;
4077c478bd9Sstevel@tonic-gate 	info->mdata->d_size = size;
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate static char *
compress(char * str,size_t * size)4117c478bd9Sstevel@tonic-gate compress(char *str, size_t *size)
4127c478bd9Sstevel@tonic-gate {
4137c478bd9Sstevel@tonic-gate 	int hash;
4147c478bd9Sstevel@tonic-gate 	int i;
4157c478bd9Sstevel@tonic-gate 	size_t temp_string_size = 0;
4167c478bd9Sstevel@tonic-gate 	size_t o_size = *size;
4177c478bd9Sstevel@tonic-gate 	char *temp_string = str;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	int *hash_key;
4207c478bd9Sstevel@tonic-gate 	size_t hash_num;
4217c478bd9Sstevel@tonic-gate 	size_t hash_end;
4227c478bd9Sstevel@tonic-gate 	size_t *hash_str;
4237c478bd9Sstevel@tonic-gate 	char *strings;
4247c478bd9Sstevel@tonic-gate 	size_t next_str;
4257c478bd9Sstevel@tonic-gate 	size_t str_size;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	hash_key = malloc(sizeof (int) * 200);
4287c478bd9Sstevel@tonic-gate 	hash_end = 200;
4297c478bd9Sstevel@tonic-gate 	hash_str = malloc(sizeof (size_t) * 200);
4307c478bd9Sstevel@tonic-gate 	str_size = o_size+1;
4317c478bd9Sstevel@tonic-gate 	strings = malloc(str_size);
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	if (hash_key == NULL || hash_str == NULL || strings == NULL) {
43457ef7aa9SRod Evans 		error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
4357c478bd9Sstevel@tonic-gate 		mcs_exit(FAILURE);
4367c478bd9Sstevel@tonic-gate 	}
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	hash_num = 0;
4397c478bd9Sstevel@tonic-gate 	next_str = 0;
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	while (temp_string_size < o_size)  {
4427c478bd9Sstevel@tonic-gate 		size_t pos;
4437c478bd9Sstevel@tonic-gate 		char c;
4447c478bd9Sstevel@tonic-gate 		/*
4457c478bd9Sstevel@tonic-gate 		 * Get a string
4467c478bd9Sstevel@tonic-gate 		 */
4477c478bd9Sstevel@tonic-gate 		pos = next_str;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 		while ((c = *(temp_string++)) != '\0' &&
4507c478bd9Sstevel@tonic-gate 		    (temp_string_size + (next_str - pos)) <= o_size) {
4517c478bd9Sstevel@tonic-gate 			if (next_str >= str_size) {
4527c478bd9Sstevel@tonic-gate 				str_size *= 2;
4537c478bd9Sstevel@tonic-gate 				if ((strings = (char *)
4547c478bd9Sstevel@tonic-gate 				    realloc(strings, str_size)) == NULL) {
45557ef7aa9SRod Evans 					error_message(MALLOC_ERROR, PLAIN_ERROR,
45657ef7aa9SRod Evans 					    NULL, prog);
4577c478bd9Sstevel@tonic-gate 					mcs_exit(FAILURE);
4587c478bd9Sstevel@tonic-gate 				}
4597c478bd9Sstevel@tonic-gate 			}
4607c478bd9Sstevel@tonic-gate 			strings[next_str++] = c;
4617c478bd9Sstevel@tonic-gate 		}
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 		if (next_str >= str_size) {
4647c478bd9Sstevel@tonic-gate 			str_size *= 2;
4657c478bd9Sstevel@tonic-gate 			if ((strings = (char *)
4667c478bd9Sstevel@tonic-gate 			    realloc(strings, str_size)) == NULL) {
46757ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
46857ef7aa9SRod Evans 				    prog);
4697c478bd9Sstevel@tonic-gate 				mcs_exit(FAILURE);
4707c478bd9Sstevel@tonic-gate 			}
4717c478bd9Sstevel@tonic-gate 		}
4726888a8baSToomas Soome 		strings[next_str++] = '\0';
4737c478bd9Sstevel@tonic-gate 		/*
4747c478bd9Sstevel@tonic-gate 		 * End get string
4757c478bd9Sstevel@tonic-gate 		 */
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 		temp_string_size += (next_str - pos);
4787c478bd9Sstevel@tonic-gate 		hash = dohash(pos + strings);
4797c478bd9Sstevel@tonic-gate 		for (i = 0; i < hash_num; i++) {
4807c478bd9Sstevel@tonic-gate 			if (hash != hash_key[i])
4817c478bd9Sstevel@tonic-gate 				continue;
4827c478bd9Sstevel@tonic-gate 			if (strcmp(pos + strings, hash_str[i] + strings) == 0)
4837c478bd9Sstevel@tonic-gate 				break;
4847c478bd9Sstevel@tonic-gate 		}
4857c478bd9Sstevel@tonic-gate 		if (i != hash_num) {
4867c478bd9Sstevel@tonic-gate 			next_str = pos;
4877c478bd9Sstevel@tonic-gate 			continue;
4887c478bd9Sstevel@tonic-gate 		}
4897c478bd9Sstevel@tonic-gate 		if (hash_num == hash_end) {
4907c478bd9Sstevel@tonic-gate 			hash_end *= 2;
4917c478bd9Sstevel@tonic-gate 			hash_key = realloc((char *)hash_key,
4920d15df17Sab 			    hash_end * sizeof (int));
4937c478bd9Sstevel@tonic-gate 			hash_str = realloc((char *)hash_str,
4940d15df17Sab 			    hash_end * sizeof (size_t));
4957c478bd9Sstevel@tonic-gate 			if (hash_key == NULL || hash_str == NULL) {
49657ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
49757ef7aa9SRod Evans 				    prog);
4987c478bd9Sstevel@tonic-gate 				mcs_exit(FAILURE);
4997c478bd9Sstevel@tonic-gate 			}
5007c478bd9Sstevel@tonic-gate 		}
5017c478bd9Sstevel@tonic-gate 		hash_key[hash_num] = hash;
5027c478bd9Sstevel@tonic-gate 		hash_str[hash_num++] = pos;
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	/*
5067c478bd9Sstevel@tonic-gate 	 * Clean up
5077c478bd9Sstevel@tonic-gate 	 */
5087c478bd9Sstevel@tonic-gate 	free(hash_key);
5097c478bd9Sstevel@tonic-gate 	free(hash_str);
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	/*
5127c478bd9Sstevel@tonic-gate 	 * Return
5137c478bd9Sstevel@tonic-gate 	 */
5147c478bd9Sstevel@tonic-gate 	if (next_str != o_size) {
5157c478bd9Sstevel@tonic-gate 		/*
5167c478bd9Sstevel@tonic-gate 		 * string compressed.
5177c478bd9Sstevel@tonic-gate 		 */
5187c478bd9Sstevel@tonic-gate 		*size = next_str;
5197c478bd9Sstevel@tonic-gate 		free(str);
5207c478bd9Sstevel@tonic-gate 		str = malloc(next_str);
5217c478bd9Sstevel@tonic-gate 		(void) memcpy(str, strings, next_str);
5227c478bd9Sstevel@tonic-gate 	}
5237c478bd9Sstevel@tonic-gate 	free(strings);
5247c478bd9Sstevel@tonic-gate 	return (str);
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate static int
dohash(char * str)5287c478bd9Sstevel@tonic-gate dohash(char *str)
5297c478bd9Sstevel@tonic-gate {
5307c478bd9Sstevel@tonic-gate 	long sum;
5317c478bd9Sstevel@tonic-gate 	unsigned shift;
5327c478bd9Sstevel@tonic-gate 	int t;
5337c478bd9Sstevel@tonic-gate 	sum = 1;
5346888a8baSToomas Soome 	for (shift = 0; (t = *str++) != 0; shift += 7) {
5357c478bd9Sstevel@tonic-gate 		sum += (long)t << (shift %= HALFLONG);
5367c478bd9Sstevel@tonic-gate 	}
5377c478bd9Sstevel@tonic-gate 	sum = low(sum) + high(sum);
5387c478bd9Sstevel@tonic-gate 	/* LINTED */
5397c478bd9Sstevel@tonic-gate 	return ((short)low(sum) + (short)high(sum));
5407c478bd9Sstevel@tonic-gate }
541