xref: /titanic_52/usr/src/cmd/sgs/mcs/common/utils.c (revision 57ef7aa924e4bfdf3118d9b5b4285dfc94b632f3)
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
50d15df17Sab196087  * Common Development and Distribution License (the "License").
60d15df17Sab196087  * 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 /*
28*57ef7aa9SRod Evans  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
297c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include "mcs.h"
337c478bd9Sstevel@tonic-gate #include "extern.h"
347c478bd9Sstevel@tonic-gate #include "gelf.h"
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate  * Function prototypes.
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate static void docompress(section_info_table *);
407c478bd9Sstevel@tonic-gate static char *compress(char *, size_t *);
417c478bd9Sstevel@tonic-gate static void doappend(char *, section_info_table *);
427c478bd9Sstevel@tonic-gate static void doprint(char *, section_info_table *);
437c478bd9Sstevel@tonic-gate static void dozap(section_info_table *);
447c478bd9Sstevel@tonic-gate static int dohash(char *);
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate  * Apply the actions specified by the user.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate int
527c478bd9Sstevel@tonic-gate apply_action(section_info_table *info, char *cur_file, Cmd_Info *cmd_info)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate 	int act_index;
557c478bd9Sstevel@tonic-gate 	int ret = 0;
567c478bd9Sstevel@tonic-gate 	GElf_Shdr shdr;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	(void) gelf_getshdr(info->scn, &shdr);
597c478bd9Sstevel@tonic-gate 	for (act_index = 0; act_index < actmax; act_index++) {
607c478bd9Sstevel@tonic-gate 		Action[act_index].a_cnt++;
617c478bd9Sstevel@tonic-gate 		switch (Action[act_index].a_action) {
627c478bd9Sstevel@tonic-gate 		case ACT_ZAP:
637c478bd9Sstevel@tonic-gate 			if (GET_ACTION(info->flags) == ACT_DELETE)
647c478bd9Sstevel@tonic-gate 				break;
657c478bd9Sstevel@tonic-gate 			dozap(info);
667c478bd9Sstevel@tonic-gate 			SET_ACTION(info->flags, ACT_ZAP);
677c478bd9Sstevel@tonic-gate 			SET_MODIFIED(info->flags);
687c478bd9Sstevel@tonic-gate 			break;
697c478bd9Sstevel@tonic-gate 		case ACT_PRINT:
707c478bd9Sstevel@tonic-gate 			if (GET_ACTION(info->flags) == ACT_DELETE)
717c478bd9Sstevel@tonic-gate 				break;
727c478bd9Sstevel@tonic-gate 			if (shdr.sh_type == SHT_NOBITS) {
730d15df17Sab196087 				error_message(ACT_PRINT_ERROR, PLAIN_ERROR,
74*57ef7aa9SRod Evans 				    NULL, prog, cur_file, SECT_NAME);
757c478bd9Sstevel@tonic-gate 				break;
767c478bd9Sstevel@tonic-gate 			}
777c478bd9Sstevel@tonic-gate 			doprint(cur_file, info);
787c478bd9Sstevel@tonic-gate 			break;
797c478bd9Sstevel@tonic-gate 		case ACT_DELETE:
807c478bd9Sstevel@tonic-gate 			/*
817c478bd9Sstevel@tonic-gate 			 * If I am strip command, this is the
827c478bd9Sstevel@tonic-gate 			 * only action I can take.
837c478bd9Sstevel@tonic-gate 			 */
847c478bd9Sstevel@tonic-gate 			if (GET_ACTION(info->flags) == ACT_DELETE)
857c478bd9Sstevel@tonic-gate 				break;
867c478bd9Sstevel@tonic-gate 			if (GET_LOC(info->flags) == IN) {
877c478bd9Sstevel@tonic-gate 				/*
887c478bd9Sstevel@tonic-gate 				 * If I am 'strip', I have to
897c478bd9Sstevel@tonic-gate 				 * unset the candidate flag and
907c478bd9Sstevel@tonic-gate 				 * unset the error return code.
917c478bd9Sstevel@tonic-gate 				 */
927c478bd9Sstevel@tonic-gate 				if (CHK_OPT(info, I_AM_STRIP)) {
937c478bd9Sstevel@tonic-gate 					ret = 0;
947c478bd9Sstevel@tonic-gate 					UNSET_CANDIDATE(info->flags);
957c478bd9Sstevel@tonic-gate 				} else {
960d15df17Sab196087 					char *name = info->name;
970d15df17Sab196087 
987c478bd9Sstevel@tonic-gate 					ret++;
990d15df17Sab196087 					if (name == NULL)
1000d15df17Sab196087 						name = gettext("<unknown>");
1017c478bd9Sstevel@tonic-gate 					error_message(ACT_DELETE1_ERROR,
102*57ef7aa9SRod Evans 					    PLAIN_ERROR, NULL,
1030d15df17Sab196087 					    prog, cur_file, name);
1047c478bd9Sstevel@tonic-gate 				}
1057c478bd9Sstevel@tonic-gate 				break;
1067c478bd9Sstevel@tonic-gate 			} else if (info->rel_loc == IN) {
1077c478bd9Sstevel@tonic-gate 				/*
1087c478bd9Sstevel@tonic-gate 				 * If I am 'strip', I have to
1097c478bd9Sstevel@tonic-gate 				 * unset the candidate flag and
1107c478bd9Sstevel@tonic-gate 				 * unset the error return code.
1117c478bd9Sstevel@tonic-gate 				 */
1127c478bd9Sstevel@tonic-gate 				if (CHK_OPT(info, I_AM_STRIP)) {
1137c478bd9Sstevel@tonic-gate 					ret = 0;
1147c478bd9Sstevel@tonic-gate 					UNSET_CANDIDATE(info->flags);
1157c478bd9Sstevel@tonic-gate 				} else {
1167c478bd9Sstevel@tonic-gate 					ret++;
1177c478bd9Sstevel@tonic-gate 					error_message(ACT_DELETE2_ERROR,
118*57ef7aa9SRod Evans 					    PLAIN_ERROR, NULL,
1197c478bd9Sstevel@tonic-gate 					    prog, cur_file, SECT_NAME,
1207c478bd9Sstevel@tonic-gate 					    info->rel_name);
1217c478bd9Sstevel@tonic-gate 				}
1227c478bd9Sstevel@tonic-gate 				break;
1237c478bd9Sstevel@tonic-gate 			} else if (GET_LOC(info->flags) == PRIOR) {
1247c478bd9Sstevel@tonic-gate 				/*
1257c478bd9Sstevel@tonic-gate 				 * I can not delete this
1267c478bd9Sstevel@tonic-gate 				 * section. I can only NULL
1277c478bd9Sstevel@tonic-gate 				 * this out.
1287c478bd9Sstevel@tonic-gate 				 */
1297c478bd9Sstevel@tonic-gate 				info->secno = (GElf_Word)NULLED;
1307c478bd9Sstevel@tonic-gate 				(cmd_info->no_of_nulled)++;
1317c478bd9Sstevel@tonic-gate 			} else {
1327c478bd9Sstevel@tonic-gate 				info->secno = (GElf_Word)DELETED;
1337c478bd9Sstevel@tonic-gate 				(cmd_info->no_of_delete)++;
1347c478bd9Sstevel@tonic-gate 			}
1357c478bd9Sstevel@tonic-gate 			SET_ACTION(info->flags, ACT_DELETE);
1367c478bd9Sstevel@tonic-gate 			SET_MODIFIED(info->flags);
1377c478bd9Sstevel@tonic-gate 			break;
1387c478bd9Sstevel@tonic-gate 		case ACT_APPEND:
1397c478bd9Sstevel@tonic-gate 			if (shdr.sh_type == SHT_NOBITS) {
1407c478bd9Sstevel@tonic-gate 				ret++;
141*57ef7aa9SRod Evans 				error_message(ACT_APPEND1_ERROR, PLAIN_ERROR,
142*57ef7aa9SRod Evans 				    NULL, prog, cur_file, SECT_NAME);
1437c478bd9Sstevel@tonic-gate 				break;
1447c478bd9Sstevel@tonic-gate 			} else if (GET_LOC(info->flags) == IN) {
1457c478bd9Sstevel@tonic-gate 				ret++;
146*57ef7aa9SRod Evans 				error_message(ACT_APPEND2_ERROR, PLAIN_ERROR,
147*57ef7aa9SRod Evans 				    NULL, prog, cur_file, SECT_NAME);
1487c478bd9Sstevel@tonic-gate 				break;
1497c478bd9Sstevel@tonic-gate 			}
1507c478bd9Sstevel@tonic-gate 			doappend(Action[act_index].a_string, info);
1517c478bd9Sstevel@tonic-gate 			(cmd_info->no_of_append)++;
1527c478bd9Sstevel@tonic-gate 			info->secno = info->osecno;
1537c478bd9Sstevel@tonic-gate 			SET_ACTION(info->flags, ACT_APPEND);
1547c478bd9Sstevel@tonic-gate 			SET_MODIFIED(info->flags);
1557c478bd9Sstevel@tonic-gate 			if (GET_LOC(info->flags) == PRIOR)
1567c478bd9Sstevel@tonic-gate 				info->secno = (GElf_Word)EXPANDED;
1577c478bd9Sstevel@tonic-gate 			break;
1587c478bd9Sstevel@tonic-gate 		case ACT_COMPRESS:
1597c478bd9Sstevel@tonic-gate 			/*
1607c478bd9Sstevel@tonic-gate 			 * If this section is already deleted,
1617c478bd9Sstevel@tonic-gate 			 * don't do anything.
1627c478bd9Sstevel@tonic-gate 			 */
1637c478bd9Sstevel@tonic-gate 			if (GET_ACTION(info->flags) == ACT_DELETE)
1647c478bd9Sstevel@tonic-gate 				break;
1657c478bd9Sstevel@tonic-gate 			if (shdr.sh_type == SHT_NOBITS) {
1667c478bd9Sstevel@tonic-gate 				ret++;
167*57ef7aa9SRod Evans 				error_message(ACT_COMPRESS1_ERROR, PLAIN_ERROR,
168*57ef7aa9SRod Evans 				    NULL, prog, cur_file, SECT_NAME);
1697c478bd9Sstevel@tonic-gate 				break;
1707c478bd9Sstevel@tonic-gate 			} else if (GET_LOC(info->flags) == IN) {
1717c478bd9Sstevel@tonic-gate 				ret++;
172*57ef7aa9SRod Evans 				error_message(ACT_COMPRESS2_ERROR, PLAIN_ERROR,
173*57ef7aa9SRod Evans 				    NULL, prog, cur_file, SECT_NAME);
1747c478bd9Sstevel@tonic-gate 				break;
1757c478bd9Sstevel@tonic-gate 			}
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 			docompress(info);
1787c478bd9Sstevel@tonic-gate 			(cmd_info->no_of_compressed)++;
1797c478bd9Sstevel@tonic-gate 			SET_ACTION(info->flags, ACT_COMPRESS);
1807c478bd9Sstevel@tonic-gate 			SET_MODIFIED(info->flags);
1817c478bd9Sstevel@tonic-gate 			if (GET_LOC(info->flags) == PRIOR)
1827c478bd9Sstevel@tonic-gate 				info->secno = (GElf_Word)SHRUNK;
1837c478bd9Sstevel@tonic-gate 			break;
1847c478bd9Sstevel@tonic-gate 		}
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 	return (ret);
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate  * ACT_ZAP
1917c478bd9Sstevel@tonic-gate  */
1927c478bd9Sstevel@tonic-gate static void
1937c478bd9Sstevel@tonic-gate dozap(section_info_table *info)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate 	Elf_Data *data;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	info->mdata = data = malloc(sizeof (Elf_Data));
1987c478bd9Sstevel@tonic-gate 	if (data == NULL) {
199*57ef7aa9SRod Evans 		error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
200d1477c77SAli Bahrami 		mcs_exit(FAILURE);
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 	*data = *info->data;
2037c478bd9Sstevel@tonic-gate 	data->d_buf = calloc(1, data->d_size);
2047c478bd9Sstevel@tonic-gate 	if (data->d_buf == NULL) {
205*57ef7aa9SRod Evans 		error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
206d1477c77SAli Bahrami 		mcs_exit(FAILURE);
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate /*
2117c478bd9Sstevel@tonic-gate  * ACT_PRINT
2127c478bd9Sstevel@tonic-gate  */
2137c478bd9Sstevel@tonic-gate static void
2147c478bd9Sstevel@tonic-gate doprint(char *cur_file, section_info_table *info)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate 	Elf_Data *data;
2177c478bd9Sstevel@tonic-gate 	size_t	temp_size;
2187c478bd9Sstevel@tonic-gate 	char	*temp_string;
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	if (GET_MODIFIED(info->flags) == 0)
2217c478bd9Sstevel@tonic-gate 		data = info->data;
2227c478bd9Sstevel@tonic-gate 	else
2237c478bd9Sstevel@tonic-gate 		data = info->mdata;
2247c478bd9Sstevel@tonic-gate 	if (data == 0)
2257c478bd9Sstevel@tonic-gate 		return;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	temp_size = data->d_size;
2287c478bd9Sstevel@tonic-gate 	temp_string = data->d_buf;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (temp_size == 0)
2317c478bd9Sstevel@tonic-gate 		return;
2327c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "%s:\n", cur_file);
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	while (temp_size--) {
2357c478bd9Sstevel@tonic-gate 		char c = *temp_string++;
2367c478bd9Sstevel@tonic-gate 		switch (c) {
2377c478bd9Sstevel@tonic-gate 		case '\0':
2387c478bd9Sstevel@tonic-gate 			(void) putchar('\n');
2397c478bd9Sstevel@tonic-gate 			break;
2407c478bd9Sstevel@tonic-gate 		default:
2417c478bd9Sstevel@tonic-gate 			(void) putchar(c);
2427c478bd9Sstevel@tonic-gate 			break;
2437c478bd9Sstevel@tonic-gate 		}
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 	(void) putchar('\n');
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate  * ACT_APPEND
2507c478bd9Sstevel@tonic-gate  */
2517c478bd9Sstevel@tonic-gate static void
2527c478bd9Sstevel@tonic-gate doappend(char *a_string, section_info_table *info)
2537c478bd9Sstevel@tonic-gate {
2547c478bd9Sstevel@tonic-gate 	Elf_Data *data;
2557c478bd9Sstevel@tonic-gate 	char *p;
2567c478bd9Sstevel@tonic-gate 	size_t len;
2577c478bd9Sstevel@tonic-gate 	char *tp;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	/*
260835cdddcSab196087 	 * Get the length of the string to be added. We accept any
261835cdddcSab196087 	 * string (even null), as this is arbitrary user defined text.
262835cdddcSab196087 	 *
263835cdddcSab196087 	 * The caller expects this routine to replace a NULL info->mdata
264835cdddcSab196087 	 * field with a pointer to a freshly allocated copy. Any attempt
265835cdddcSab196087 	 * to optimize away a null string append would have to deal with
266835cdddcSab196087 	 * that, as failing to do so will cause a segfault when the NULL
267835cdddcSab196087 	 * mdata field is dereferenced. Accepting null strings in
268835cdddcSab196087 	 * this very unimportant case eliminates the need for that.
2697c478bd9Sstevel@tonic-gate 	 */
2707c478bd9Sstevel@tonic-gate 	len = strlen(a_string);
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	/*
2737c478bd9Sstevel@tonic-gate 	 * Every modification operation will be done
2747c478bd9Sstevel@tonic-gate 	 * to a new Elf_Data descriptor.
2757c478bd9Sstevel@tonic-gate 	 */
2767c478bd9Sstevel@tonic-gate 	if (info->mdata == 0) {
2777c478bd9Sstevel@tonic-gate 		/*
2787c478bd9Sstevel@tonic-gate 		 * mdata is not allocated yet.
2797c478bd9Sstevel@tonic-gate 		 * Allocate the data and set it.
2807c478bd9Sstevel@tonic-gate 		 */
2817c478bd9Sstevel@tonic-gate 		info->mdata = data = calloc(1, sizeof (Elf_Data));
2827c478bd9Sstevel@tonic-gate 		if (data == NULL) {
283*57ef7aa9SRod Evans 			error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
284d1477c77SAli Bahrami 			mcs_exit(FAILURE);
2857c478bd9Sstevel@tonic-gate 		}
2867c478bd9Sstevel@tonic-gate 		*data = *info->data;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 		/*
2897c478bd9Sstevel@tonic-gate 		 * Check if the section is deleted or not.
2907c478bd9Sstevel@tonic-gate 		 * Or if the size is 0 or not.
2917c478bd9Sstevel@tonic-gate 		 */
2927c478bd9Sstevel@tonic-gate 		if ((GET_ACTION(info->flags) == ACT_DELETE) ||
2937c478bd9Sstevel@tonic-gate 		    data->d_size == 0) {
2947c478bd9Sstevel@tonic-gate 			/*
2957c478bd9Sstevel@tonic-gate 			 * The section was deleated.
2967c478bd9Sstevel@tonic-gate 			 * But now, the user wants to add data to this
2977c478bd9Sstevel@tonic-gate 			 * section.
2987c478bd9Sstevel@tonic-gate 			 */
2997c478bd9Sstevel@tonic-gate 			data->d_buf = calloc(1, len + 2);
300*57ef7aa9SRod Evans 			if (data->d_buf == NULL) {
301*57ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
302*57ef7aa9SRod Evans 				    prog);
303d1477c77SAli Bahrami 				mcs_exit(FAILURE);
3047c478bd9Sstevel@tonic-gate 			}
3057c478bd9Sstevel@tonic-gate 			tp = (char *)data->d_buf;
3067c478bd9Sstevel@tonic-gate 			(void) memcpy(& tp[1], a_string, len + 1);
3077c478bd9Sstevel@tonic-gate 			data->d_size = len + 2;
3087c478bd9Sstevel@tonic-gate 		} else {
3097c478bd9Sstevel@tonic-gate 			/*
3107c478bd9Sstevel@tonic-gate 			 * The user wants to add data to the section.
3117c478bd9Sstevel@tonic-gate 			 * I am not going to change the original data.
3127c478bd9Sstevel@tonic-gate 			 * Do the modification on the new one.
3137c478bd9Sstevel@tonic-gate 			 */
3147c478bd9Sstevel@tonic-gate 			p = malloc(len + 1 + data->d_size);
3157c478bd9Sstevel@tonic-gate 			if (p == NULL) {
316*57ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
317*57ef7aa9SRod Evans 				    prog);
318d1477c77SAli Bahrami 				mcs_exit(FAILURE);
3197c478bd9Sstevel@tonic-gate 			}
3207c478bd9Sstevel@tonic-gate 			(void) memcpy(p, data->d_buf, data->d_size);
3217c478bd9Sstevel@tonic-gate 			(void) memcpy(&p[data->d_size], a_string, len + 1);
3227c478bd9Sstevel@tonic-gate 			data->d_buf = p;
3237c478bd9Sstevel@tonic-gate 			data->d_size = data->d_size + len + 1;
3247c478bd9Sstevel@tonic-gate 		}
3257c478bd9Sstevel@tonic-gate 	} else {
3267c478bd9Sstevel@tonic-gate 		/*
3277c478bd9Sstevel@tonic-gate 		 * mdata is already allocated.
3287c478bd9Sstevel@tonic-gate 		 * Modify it.
3297c478bd9Sstevel@tonic-gate 		 */
3307c478bd9Sstevel@tonic-gate 		data = info->mdata;
3317c478bd9Sstevel@tonic-gate 		if ((GET_ACTION(info->flags) == ACT_DELETE) ||
3327c478bd9Sstevel@tonic-gate 		    data->d_size == 0) {
3337c478bd9Sstevel@tonic-gate 			/*
3347c478bd9Sstevel@tonic-gate 			 * The section was deleated.
3357c478bd9Sstevel@tonic-gate 			 * But now, the user wants to add data to this
3367c478bd9Sstevel@tonic-gate 			 * section.
3377c478bd9Sstevel@tonic-gate 			 */
3387c478bd9Sstevel@tonic-gate 			if (data->d_buf)
3397c478bd9Sstevel@tonic-gate 				free(data->d_buf);
3407c478bd9Sstevel@tonic-gate 			data->d_buf = calloc(1, len + 2);
341*57ef7aa9SRod Evans 			if (data->d_buf == NULL) {
342*57ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
343*57ef7aa9SRod Evans 				    prog);
344d1477c77SAli Bahrami 				mcs_exit(FAILURE);
3457c478bd9Sstevel@tonic-gate 			}
3467c478bd9Sstevel@tonic-gate 			tp = (char *)data->d_buf;
3477c478bd9Sstevel@tonic-gate 			(void) memcpy(&tp[1], a_string, len + 1);
3487c478bd9Sstevel@tonic-gate 			data->d_size = len + 2;
3497c478bd9Sstevel@tonic-gate 		} else {
3507c478bd9Sstevel@tonic-gate 			/*
3517c478bd9Sstevel@tonic-gate 			 * The user wants to add data to the section.
3527c478bd9Sstevel@tonic-gate 			 * I am not going to change the original data.
3537c478bd9Sstevel@tonic-gate 			 * Do the modification on the new one.
3547c478bd9Sstevel@tonic-gate 			 */
3557c478bd9Sstevel@tonic-gate 			p = malloc(len + 1 + data->d_size);
3567c478bd9Sstevel@tonic-gate 			if (p == NULL) {
357*57ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
358*57ef7aa9SRod Evans 				    prog);
359d1477c77SAli Bahrami 				mcs_exit(FAILURE);
3607c478bd9Sstevel@tonic-gate 			}
3617c478bd9Sstevel@tonic-gate 			(void) memcpy(p, data->d_buf, data->d_size);
3627c478bd9Sstevel@tonic-gate 			(void) memcpy(&p[data->d_size], a_string, len + 1);
3637c478bd9Sstevel@tonic-gate 			free(data->d_buf);
3647c478bd9Sstevel@tonic-gate 			data->d_buf = p;
3657c478bd9Sstevel@tonic-gate 			data->d_size = data->d_size + len + 1;
3667c478bd9Sstevel@tonic-gate 		}
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate }
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate /*
3717c478bd9Sstevel@tonic-gate  * ACT_COMPRESS
3727c478bd9Sstevel@tonic-gate  */
3737c478bd9Sstevel@tonic-gate #define	HALFLONG 16
3747c478bd9Sstevel@tonic-gate #define	low(x)  (x&((1L<<HALFLONG)-1))
3757c478bd9Sstevel@tonic-gate #define	high(x) (x>>HALFLONG)
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate static void
3787c478bd9Sstevel@tonic-gate docompress(section_info_table *info)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate 	Elf_Data *data;
3817c478bd9Sstevel@tonic-gate 	size_t size;
3827c478bd9Sstevel@tonic-gate 	char *buf;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	if (info->mdata == 0) {
3857c478bd9Sstevel@tonic-gate 		/*
3867c478bd9Sstevel@tonic-gate 		 * mdata is not allocated yet.
3877c478bd9Sstevel@tonic-gate 		 * Allocate the data and set it.
3887c478bd9Sstevel@tonic-gate 		 */
3897c478bd9Sstevel@tonic-gate 		char *p;
3907c478bd9Sstevel@tonic-gate 		info->mdata = data = calloc(1, sizeof (Elf_Data));
3917c478bd9Sstevel@tonic-gate 		if (data == NULL) {
392*57ef7aa9SRod Evans 			error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
393d1477c77SAli Bahrami 			mcs_exit(FAILURE);
3947c478bd9Sstevel@tonic-gate 		}
3957c478bd9Sstevel@tonic-gate 		*data = *info->data;
3967c478bd9Sstevel@tonic-gate 		p = malloc(data->d_size);
3977c478bd9Sstevel@tonic-gate 		(void) memcpy(p, (char *)data->d_buf, data->d_size);
3987c478bd9Sstevel@tonic-gate 		data->d_buf = p;
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate 	size = info->mdata->d_size;
4017c478bd9Sstevel@tonic-gate 	buf = (char *)info->mdata->d_buf;
4027c478bd9Sstevel@tonic-gate 	buf = compress(buf, &size);
4037c478bd9Sstevel@tonic-gate 	info->mdata->d_buf = buf;
4047c478bd9Sstevel@tonic-gate 	info->mdata->d_size = size;
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate static char *
4087c478bd9Sstevel@tonic-gate compress(char *str, size_t *size)
4097c478bd9Sstevel@tonic-gate {
4107c478bd9Sstevel@tonic-gate 	int hash;
4117c478bd9Sstevel@tonic-gate 	int i;
4127c478bd9Sstevel@tonic-gate 	size_t temp_string_size = 0;
4137c478bd9Sstevel@tonic-gate 	size_t o_size = *size;
4147c478bd9Sstevel@tonic-gate 	char *temp_string = str;
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	int *hash_key;
4177c478bd9Sstevel@tonic-gate 	size_t hash_num;
4187c478bd9Sstevel@tonic-gate 	size_t hash_end;
4197c478bd9Sstevel@tonic-gate 	size_t *hash_str;
4207c478bd9Sstevel@tonic-gate 	char *strings;
4217c478bd9Sstevel@tonic-gate 	size_t next_str;
4227c478bd9Sstevel@tonic-gate 	size_t str_size;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	hash_key = malloc(sizeof (int) * 200);
4257c478bd9Sstevel@tonic-gate 	hash_end = 200;
4267c478bd9Sstevel@tonic-gate 	hash_str = malloc(sizeof (size_t) * 200);
4277c478bd9Sstevel@tonic-gate 	str_size = o_size+1;
4287c478bd9Sstevel@tonic-gate 	strings = malloc(str_size);
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	if (hash_key == NULL || hash_str == NULL || strings == NULL) {
431*57ef7aa9SRod Evans 		error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
4327c478bd9Sstevel@tonic-gate 		mcs_exit(FAILURE);
4337c478bd9Sstevel@tonic-gate 	}
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	hash_num = 0;
4367c478bd9Sstevel@tonic-gate 	next_str = 0;
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	while (temp_string_size < o_size)  {
4397c478bd9Sstevel@tonic-gate 		size_t pos;
4407c478bd9Sstevel@tonic-gate 		char c;
4417c478bd9Sstevel@tonic-gate 		/*
4427c478bd9Sstevel@tonic-gate 		 * Get a string
4437c478bd9Sstevel@tonic-gate 		 */
4447c478bd9Sstevel@tonic-gate 		pos = next_str;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 		while ((c = *(temp_string++)) != '\0' &&
4477c478bd9Sstevel@tonic-gate 		    (temp_string_size + (next_str - pos)) <= o_size) {
4487c478bd9Sstevel@tonic-gate 			if (next_str >= str_size) {
4497c478bd9Sstevel@tonic-gate 				str_size *= 2;
4507c478bd9Sstevel@tonic-gate 				if ((strings = (char *)
4517c478bd9Sstevel@tonic-gate 				    realloc(strings, str_size)) == NULL) {
452*57ef7aa9SRod Evans 					error_message(MALLOC_ERROR, PLAIN_ERROR,
453*57ef7aa9SRod Evans 					    NULL, prog);
4547c478bd9Sstevel@tonic-gate 					mcs_exit(FAILURE);
4557c478bd9Sstevel@tonic-gate 				}
4567c478bd9Sstevel@tonic-gate 			}
4577c478bd9Sstevel@tonic-gate 			strings[next_str++] = c;
4587c478bd9Sstevel@tonic-gate 		}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 		if (next_str >= str_size) {
4617c478bd9Sstevel@tonic-gate 			str_size *= 2;
4627c478bd9Sstevel@tonic-gate 			if ((strings = (char *)
4637c478bd9Sstevel@tonic-gate 			    realloc(strings, str_size)) == NULL) {
464*57ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
465*57ef7aa9SRod Evans 				    prog);
4667c478bd9Sstevel@tonic-gate 				mcs_exit(FAILURE);
4677c478bd9Sstevel@tonic-gate 			}
4687c478bd9Sstevel@tonic-gate 		}
4697c478bd9Sstevel@tonic-gate 		strings[next_str++] = NULL;
4707c478bd9Sstevel@tonic-gate 		/*
4717c478bd9Sstevel@tonic-gate 		 * End get string
4727c478bd9Sstevel@tonic-gate 		 */
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 		temp_string_size += (next_str - pos);
4757c478bd9Sstevel@tonic-gate 		hash = dohash(pos + strings);
4767c478bd9Sstevel@tonic-gate 		for (i = 0; i < hash_num; i++) {
4777c478bd9Sstevel@tonic-gate 			if (hash != hash_key[i])
4787c478bd9Sstevel@tonic-gate 				continue;
4797c478bd9Sstevel@tonic-gate 			if (strcmp(pos + strings, hash_str[i] + strings) == 0)
4807c478bd9Sstevel@tonic-gate 				break;
4817c478bd9Sstevel@tonic-gate 		}
4827c478bd9Sstevel@tonic-gate 		if (i != hash_num) {
4837c478bd9Sstevel@tonic-gate 			next_str = pos;
4847c478bd9Sstevel@tonic-gate 			continue;
4857c478bd9Sstevel@tonic-gate 		}
4867c478bd9Sstevel@tonic-gate 		if (hash_num == hash_end) {
4877c478bd9Sstevel@tonic-gate 			hash_end *= 2;
4887c478bd9Sstevel@tonic-gate 			hash_key = realloc((char *)hash_key,
4897c478bd9Sstevel@tonic-gate 			    hash_end * sizeof (int));
4907c478bd9Sstevel@tonic-gate 			hash_str = realloc((char *)hash_str,
4917c478bd9Sstevel@tonic-gate 			    hash_end * sizeof (size_t));
4927c478bd9Sstevel@tonic-gate 			if (hash_key == NULL || hash_str == NULL) {
493*57ef7aa9SRod Evans 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
494*57ef7aa9SRod Evans 				    prog);
4957c478bd9Sstevel@tonic-gate 				mcs_exit(FAILURE);
4967c478bd9Sstevel@tonic-gate 			}
4977c478bd9Sstevel@tonic-gate 		}
4987c478bd9Sstevel@tonic-gate 		hash_key[hash_num] = hash;
4997c478bd9Sstevel@tonic-gate 		hash_str[hash_num++] = pos;
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	/*
5037c478bd9Sstevel@tonic-gate 	 * Clean up
5047c478bd9Sstevel@tonic-gate 	 */
5057c478bd9Sstevel@tonic-gate 	free(hash_key);
5067c478bd9Sstevel@tonic-gate 	free(hash_str);
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	/*
5097c478bd9Sstevel@tonic-gate 	 * Return
5107c478bd9Sstevel@tonic-gate 	 */
5117c478bd9Sstevel@tonic-gate 	if (next_str != o_size) {
5127c478bd9Sstevel@tonic-gate 		/*
5137c478bd9Sstevel@tonic-gate 		 * string compressed.
5147c478bd9Sstevel@tonic-gate 		 */
5157c478bd9Sstevel@tonic-gate 		*size = next_str;
5167c478bd9Sstevel@tonic-gate 		free(str);
5177c478bd9Sstevel@tonic-gate 		str = malloc(next_str);
5187c478bd9Sstevel@tonic-gate 		(void) memcpy(str, strings, next_str);
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 	free(strings);
5217c478bd9Sstevel@tonic-gate 	return (str);
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate static int
5257c478bd9Sstevel@tonic-gate dohash(char *str)
5267c478bd9Sstevel@tonic-gate {
5277c478bd9Sstevel@tonic-gate 	long sum;
5287c478bd9Sstevel@tonic-gate 	unsigned shift;
5297c478bd9Sstevel@tonic-gate 	int t;
5307c478bd9Sstevel@tonic-gate 	sum = 1;
5317c478bd9Sstevel@tonic-gate 	for (shift = 0; (t = *str++) != NULL; shift += 7) {
5327c478bd9Sstevel@tonic-gate 		sum += (long)t << (shift %= HALFLONG);
5337c478bd9Sstevel@tonic-gate 	}
5347c478bd9Sstevel@tonic-gate 	sum = low(sum) + high(sum);
5357c478bd9Sstevel@tonic-gate 	/* LINTED */
5367c478bd9Sstevel@tonic-gate 	return ((short)low(sum) + (short)high(sum));
5377c478bd9Sstevel@tonic-gate }
538