xref: /onnv-gate/usr/src/cmd/sgs/mcs/common/utils.c (revision 9131:d7741cc87056)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55154Sab196087  * Common Development and Distribution License (the "License").
65154Sab196087  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
220Sstevel@tonic-gate  *	Copyright(c) 1988 AT&T
230Sstevel@tonic-gate  *	  All Rights Reserved
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*
28*9131SRod.Evans@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
290Sstevel@tonic-gate  * Use is subject to license terms.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include "mcs.h"
330Sstevel@tonic-gate #include "extern.h"
340Sstevel@tonic-gate #include "gelf.h"
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate  * Function prototypes.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate static void docompress(section_info_table *);
400Sstevel@tonic-gate static char *compress(char *, size_t *);
410Sstevel@tonic-gate static void doappend(char *, section_info_table *);
420Sstevel@tonic-gate static void doprint(char *, section_info_table *);
430Sstevel@tonic-gate static void dozap(section_info_table *);
440Sstevel@tonic-gate static int dohash(char *);
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 
470Sstevel@tonic-gate 
480Sstevel@tonic-gate /*
490Sstevel@tonic-gate  * Apply the actions specified by the user.
500Sstevel@tonic-gate  */
510Sstevel@tonic-gate int
apply_action(section_info_table * info,char * cur_file,Cmd_Info * cmd_info)520Sstevel@tonic-gate apply_action(section_info_table *info, char *cur_file, Cmd_Info *cmd_info)
530Sstevel@tonic-gate {
540Sstevel@tonic-gate 	int act_index;
550Sstevel@tonic-gate 	int ret = 0;
560Sstevel@tonic-gate 	GElf_Shdr shdr;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate 	(void) gelf_getshdr(info->scn, &shdr);
590Sstevel@tonic-gate 	for (act_index = 0; act_index < actmax; act_index++) {
600Sstevel@tonic-gate 		Action[act_index].a_cnt++;
610Sstevel@tonic-gate 		switch (Action[act_index].a_action) {
620Sstevel@tonic-gate 		case ACT_ZAP:
630Sstevel@tonic-gate 			if (GET_ACTION(info->flags) == ACT_DELETE)
640Sstevel@tonic-gate 				break;
650Sstevel@tonic-gate 			dozap(info);
660Sstevel@tonic-gate 			SET_ACTION(info->flags, ACT_ZAP);
670Sstevel@tonic-gate 			SET_MODIFIED(info->flags);
680Sstevel@tonic-gate 			break;
690Sstevel@tonic-gate 		case ACT_PRINT:
700Sstevel@tonic-gate 			if (GET_ACTION(info->flags) == ACT_DELETE)
710Sstevel@tonic-gate 				break;
720Sstevel@tonic-gate 			if (shdr.sh_type == SHT_NOBITS) {
735154Sab196087 				error_message(ACT_PRINT_ERROR, PLAIN_ERROR,
74*9131SRod.Evans@Sun.COM 				    NULL, prog, cur_file, SECT_NAME);
750Sstevel@tonic-gate 				break;
760Sstevel@tonic-gate 			}
770Sstevel@tonic-gate 			doprint(cur_file, info);
780Sstevel@tonic-gate 			break;
790Sstevel@tonic-gate 		case ACT_DELETE:
800Sstevel@tonic-gate 			/*
810Sstevel@tonic-gate 			 * If I am strip command, this is the
820Sstevel@tonic-gate 			 * only action I can take.
830Sstevel@tonic-gate 			 */
840Sstevel@tonic-gate 			if (GET_ACTION(info->flags) == ACT_DELETE)
850Sstevel@tonic-gate 				break;
860Sstevel@tonic-gate 			if (GET_LOC(info->flags) == IN) {
870Sstevel@tonic-gate 				/*
880Sstevel@tonic-gate 				 * If I am 'strip', I have to
890Sstevel@tonic-gate 				 * unset the candidate flag and
900Sstevel@tonic-gate 				 * unset the error return code.
910Sstevel@tonic-gate 				 */
920Sstevel@tonic-gate 				if (CHK_OPT(info, I_AM_STRIP)) {
930Sstevel@tonic-gate 					ret = 0;
940Sstevel@tonic-gate 					UNSET_CANDIDATE(info->flags);
950Sstevel@tonic-gate 				} else {
965154Sab196087 					char *name = info->name;
975154Sab196087 
980Sstevel@tonic-gate 					ret++;
995154Sab196087 					if (name == NULL)
1005154Sab196087 						name = gettext("<unknown>");
1010Sstevel@tonic-gate 					error_message(ACT_DELETE1_ERROR,
102*9131SRod.Evans@Sun.COM 					    PLAIN_ERROR, NULL,
1035154Sab196087 					    prog, cur_file, name);
1040Sstevel@tonic-gate 				}
1050Sstevel@tonic-gate 				break;
1060Sstevel@tonic-gate 			} else if (info->rel_loc == IN) {
1070Sstevel@tonic-gate 				/*
1080Sstevel@tonic-gate 				 * If I am 'strip', I have to
1090Sstevel@tonic-gate 				 * unset the candidate flag and
1100Sstevel@tonic-gate 				 * unset the error return code.
1110Sstevel@tonic-gate 				 */
1120Sstevel@tonic-gate 				if (CHK_OPT(info, I_AM_STRIP)) {
1130Sstevel@tonic-gate 					ret = 0;
1140Sstevel@tonic-gate 					UNSET_CANDIDATE(info->flags);
1150Sstevel@tonic-gate 				} else {
1160Sstevel@tonic-gate 					ret++;
1170Sstevel@tonic-gate 					error_message(ACT_DELETE2_ERROR,
118*9131SRod.Evans@Sun.COM 					    PLAIN_ERROR, NULL,
1195154Sab196087 					    prog, cur_file, SECT_NAME,
1205154Sab196087 					    info->rel_name);
1210Sstevel@tonic-gate 				}
1220Sstevel@tonic-gate 				break;
1230Sstevel@tonic-gate 			} else if (GET_LOC(info->flags) == PRIOR) {
1240Sstevel@tonic-gate 				/*
1250Sstevel@tonic-gate 				 * I can not delete this
1260Sstevel@tonic-gate 				 * section. I can only NULL
1270Sstevel@tonic-gate 				 * this out.
1280Sstevel@tonic-gate 				 */
1290Sstevel@tonic-gate 				info->secno = (GElf_Word)NULLED;
1300Sstevel@tonic-gate 				(cmd_info->no_of_nulled)++;
1310Sstevel@tonic-gate 			} else {
1320Sstevel@tonic-gate 				info->secno = (GElf_Word)DELETED;
1330Sstevel@tonic-gate 				(cmd_info->no_of_delete)++;
1340Sstevel@tonic-gate 			}
1350Sstevel@tonic-gate 			SET_ACTION(info->flags, ACT_DELETE);
1360Sstevel@tonic-gate 			SET_MODIFIED(info->flags);
1370Sstevel@tonic-gate 			break;
1380Sstevel@tonic-gate 		case ACT_APPEND:
1390Sstevel@tonic-gate 			if (shdr.sh_type == SHT_NOBITS) {
1400Sstevel@tonic-gate 				ret++;
141*9131SRod.Evans@Sun.COM 				error_message(ACT_APPEND1_ERROR, PLAIN_ERROR,
142*9131SRod.Evans@Sun.COM 				    NULL, prog, cur_file, SECT_NAME);
1430Sstevel@tonic-gate 				break;
1440Sstevel@tonic-gate 			} else if (GET_LOC(info->flags) == IN) {
1450Sstevel@tonic-gate 				ret++;
146*9131SRod.Evans@Sun.COM 				error_message(ACT_APPEND2_ERROR, PLAIN_ERROR,
147*9131SRod.Evans@Sun.COM 				    NULL, prog, cur_file, SECT_NAME);
1480Sstevel@tonic-gate 				break;
1490Sstevel@tonic-gate 			}
1500Sstevel@tonic-gate 			doappend(Action[act_index].a_string, info);
1510Sstevel@tonic-gate 			(cmd_info->no_of_append)++;
1520Sstevel@tonic-gate 			info->secno = info->osecno;
1530Sstevel@tonic-gate 			SET_ACTION(info->flags, ACT_APPEND);
1540Sstevel@tonic-gate 			SET_MODIFIED(info->flags);
1550Sstevel@tonic-gate 			if (GET_LOC(info->flags) == PRIOR)
1560Sstevel@tonic-gate 				info->secno = (GElf_Word)EXPANDED;
1570Sstevel@tonic-gate 			break;
1580Sstevel@tonic-gate 		case ACT_COMPRESS:
1590Sstevel@tonic-gate 			/*
1600Sstevel@tonic-gate 			 * If this section is already deleted,
1610Sstevel@tonic-gate 			 * don't do anything.
1620Sstevel@tonic-gate 			 */
1630Sstevel@tonic-gate 			if (GET_ACTION(info->flags) == ACT_DELETE)
1640Sstevel@tonic-gate 				break;
1650Sstevel@tonic-gate 			if (shdr.sh_type == SHT_NOBITS) {
1660Sstevel@tonic-gate 				ret++;
167*9131SRod.Evans@Sun.COM 				error_message(ACT_COMPRESS1_ERROR, PLAIN_ERROR,
168*9131SRod.Evans@Sun.COM 				    NULL, prog, cur_file, SECT_NAME);
1690Sstevel@tonic-gate 				break;
1700Sstevel@tonic-gate 			} else if (GET_LOC(info->flags) == IN) {
1710Sstevel@tonic-gate 				ret++;
172*9131SRod.Evans@Sun.COM 				error_message(ACT_COMPRESS2_ERROR, PLAIN_ERROR,
173*9131SRod.Evans@Sun.COM 				    NULL, prog, cur_file, SECT_NAME);
1740Sstevel@tonic-gate 				break;
1750Sstevel@tonic-gate 			}
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 			docompress(info);
1780Sstevel@tonic-gate 			(cmd_info->no_of_compressed)++;
1790Sstevel@tonic-gate 			SET_ACTION(info->flags, ACT_COMPRESS);
1800Sstevel@tonic-gate 			SET_MODIFIED(info->flags);
1810Sstevel@tonic-gate 			if (GET_LOC(info->flags) == PRIOR)
1820Sstevel@tonic-gate 				info->secno = (GElf_Word)SHRUNK;
1830Sstevel@tonic-gate 			break;
1840Sstevel@tonic-gate 		}
1850Sstevel@tonic-gate 	}
1860Sstevel@tonic-gate 	return (ret);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate /*
1900Sstevel@tonic-gate  * ACT_ZAP
1910Sstevel@tonic-gate  */
1920Sstevel@tonic-gate static void
dozap(section_info_table * info)1930Sstevel@tonic-gate dozap(section_info_table *info)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate 	Elf_Data *data;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	info->mdata = data = malloc(sizeof (Elf_Data));
1980Sstevel@tonic-gate 	if (data == NULL) {
199*9131SRod.Evans@Sun.COM 		error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
2008223SAli.Bahrami@Sun.COM 		mcs_exit(FAILURE);
2010Sstevel@tonic-gate 	}
2020Sstevel@tonic-gate 	*data = *info->data;
2030Sstevel@tonic-gate 	data->d_buf = calloc(1, data->d_size);
2040Sstevel@tonic-gate 	if (data->d_buf == NULL) {
205*9131SRod.Evans@Sun.COM 		error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
2068223SAli.Bahrami@Sun.COM 		mcs_exit(FAILURE);
2070Sstevel@tonic-gate 	}
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate /*
2110Sstevel@tonic-gate  * ACT_PRINT
2120Sstevel@tonic-gate  */
2130Sstevel@tonic-gate static void
doprint(char * cur_file,section_info_table * info)2140Sstevel@tonic-gate doprint(char *cur_file, section_info_table *info)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate 	Elf_Data *data;
2170Sstevel@tonic-gate 	size_t	temp_size;
2180Sstevel@tonic-gate 	char	*temp_string;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	if (GET_MODIFIED(info->flags) == 0)
2210Sstevel@tonic-gate 		data = info->data;
2220Sstevel@tonic-gate 	else
2230Sstevel@tonic-gate 		data = info->mdata;
2240Sstevel@tonic-gate 	if (data == 0)
2250Sstevel@tonic-gate 		return;
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	temp_size = data->d_size;
2280Sstevel@tonic-gate 	temp_string = data->d_buf;
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	if (temp_size == 0)
2310Sstevel@tonic-gate 		return;
2320Sstevel@tonic-gate 	(void) fprintf(stdout, "%s:\n", cur_file);
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	while (temp_size--) {
2350Sstevel@tonic-gate 		char c = *temp_string++;
2360Sstevel@tonic-gate 		switch (c) {
2370Sstevel@tonic-gate 		case '\0':
2380Sstevel@tonic-gate 			(void) putchar('\n');
2390Sstevel@tonic-gate 			break;
2400Sstevel@tonic-gate 		default:
2410Sstevel@tonic-gate 			(void) putchar(c);
2420Sstevel@tonic-gate 			break;
2430Sstevel@tonic-gate 		}
2440Sstevel@tonic-gate 	}
2450Sstevel@tonic-gate 	(void) putchar('\n');
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate /*
2490Sstevel@tonic-gate  * ACT_APPEND
2500Sstevel@tonic-gate  */
2510Sstevel@tonic-gate static void
doappend(char * a_string,section_info_table * info)2520Sstevel@tonic-gate doappend(char *a_string, section_info_table *info)
2530Sstevel@tonic-gate {
2540Sstevel@tonic-gate 	Elf_Data *data;
2550Sstevel@tonic-gate 	char *p;
2560Sstevel@tonic-gate 	size_t len;
2570Sstevel@tonic-gate 	char *tp;
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 	/*
2601282Sab196087 	 * Get the length of the string to be added. We accept any
2611282Sab196087 	 * string (even null), as this is arbitrary user defined text.
2621282Sab196087 	 *
2631282Sab196087 	 * The caller expects this routine to replace a NULL info->mdata
2641282Sab196087 	 * field with a pointer to a freshly allocated copy. Any attempt
2651282Sab196087 	 * to optimize away a null string append would have to deal with
2661282Sab196087 	 * that, as failing to do so will cause a segfault when the NULL
2671282Sab196087 	 * mdata field is dereferenced. Accepting null strings in
2681282Sab196087 	 * this very unimportant case eliminates the need for that.
2690Sstevel@tonic-gate 	 */
2700Sstevel@tonic-gate 	len = strlen(a_string);
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	/*
2730Sstevel@tonic-gate 	 * Every modification operation will be done
2740Sstevel@tonic-gate 	 * to a new Elf_Data descriptor.
2750Sstevel@tonic-gate 	 */
2760Sstevel@tonic-gate 	if (info->mdata == 0) {
2770Sstevel@tonic-gate 		/*
2780Sstevel@tonic-gate 		 * mdata is not allocated yet.
2790Sstevel@tonic-gate 		 * Allocate the data and set it.
2800Sstevel@tonic-gate 		 */
2810Sstevel@tonic-gate 		info->mdata = data = calloc(1, sizeof (Elf_Data));
2820Sstevel@tonic-gate 		if (data == NULL) {
283*9131SRod.Evans@Sun.COM 			error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
2848223SAli.Bahrami@Sun.COM 			mcs_exit(FAILURE);
2850Sstevel@tonic-gate 		}
2860Sstevel@tonic-gate 		*data = *info->data;
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 		/*
2890Sstevel@tonic-gate 		 * Check if the section is deleted or not.
2900Sstevel@tonic-gate 		 * Or if the size is 0 or not.
2910Sstevel@tonic-gate 		 */
2920Sstevel@tonic-gate 		if ((GET_ACTION(info->flags) == ACT_DELETE) ||
2930Sstevel@tonic-gate 		    data->d_size == 0) {
2940Sstevel@tonic-gate 			/*
2950Sstevel@tonic-gate 			 * The section was deleated.
2960Sstevel@tonic-gate 			 * But now, the user wants to add data to this
2970Sstevel@tonic-gate 			 * section.
2980Sstevel@tonic-gate 			 */
2990Sstevel@tonic-gate 			data->d_buf = calloc(1, len + 2);
300*9131SRod.Evans@Sun.COM 			if (data->d_buf == NULL) {
301*9131SRod.Evans@Sun.COM 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
302*9131SRod.Evans@Sun.COM 				    prog);
3038223SAli.Bahrami@Sun.COM 				mcs_exit(FAILURE);
3040Sstevel@tonic-gate 			}
3050Sstevel@tonic-gate 			tp = (char *)data->d_buf;
3060Sstevel@tonic-gate 			(void) memcpy(& tp[1], a_string, len + 1);
3070Sstevel@tonic-gate 			data->d_size = len + 2;
3080Sstevel@tonic-gate 		} else {
3090Sstevel@tonic-gate 			/*
3100Sstevel@tonic-gate 			 * The user wants to add data to the section.
3110Sstevel@tonic-gate 			 * I am not going to change the original data.
3120Sstevel@tonic-gate 			 * Do the modification on the new one.
3130Sstevel@tonic-gate 			 */
3140Sstevel@tonic-gate 			p = malloc(len + 1 + data->d_size);
3150Sstevel@tonic-gate 			if (p == NULL) {
316*9131SRod.Evans@Sun.COM 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
317*9131SRod.Evans@Sun.COM 				    prog);
3188223SAli.Bahrami@Sun.COM 				mcs_exit(FAILURE);
3190Sstevel@tonic-gate 			}
3200Sstevel@tonic-gate 			(void) memcpy(p, data->d_buf, data->d_size);
3210Sstevel@tonic-gate 			(void) memcpy(&p[data->d_size], a_string, len + 1);
3220Sstevel@tonic-gate 			data->d_buf = p;
3230Sstevel@tonic-gate 			data->d_size = data->d_size + len + 1;
3240Sstevel@tonic-gate 		}
3250Sstevel@tonic-gate 	} else {
3260Sstevel@tonic-gate 		/*
3270Sstevel@tonic-gate 		 * mdata is already allocated.
3280Sstevel@tonic-gate 		 * Modify it.
3290Sstevel@tonic-gate 		 */
3300Sstevel@tonic-gate 		data = info->mdata;
3310Sstevel@tonic-gate 		if ((GET_ACTION(info->flags) == ACT_DELETE) ||
3320Sstevel@tonic-gate 		    data->d_size == 0) {
3330Sstevel@tonic-gate 			/*
3340Sstevel@tonic-gate 			 * The section was deleated.
3350Sstevel@tonic-gate 			 * But now, the user wants to add data to this
3360Sstevel@tonic-gate 			 * section.
3370Sstevel@tonic-gate 			 */
3380Sstevel@tonic-gate 			if (data->d_buf)
3390Sstevel@tonic-gate 				free(data->d_buf);
3400Sstevel@tonic-gate 			data->d_buf = calloc(1, len + 2);
341*9131SRod.Evans@Sun.COM 			if (data->d_buf == NULL) {
342*9131SRod.Evans@Sun.COM 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
343*9131SRod.Evans@Sun.COM 				    prog);
3448223SAli.Bahrami@Sun.COM 				mcs_exit(FAILURE);
3450Sstevel@tonic-gate 			}
3460Sstevel@tonic-gate 			tp = (char *)data->d_buf;
3470Sstevel@tonic-gate 			(void) memcpy(&tp[1], a_string, len + 1);
3480Sstevel@tonic-gate 			data->d_size = len + 2;
3490Sstevel@tonic-gate 		} else {
3500Sstevel@tonic-gate 			/*
3510Sstevel@tonic-gate 			 * The user wants to add data to the section.
3520Sstevel@tonic-gate 			 * I am not going to change the original data.
3530Sstevel@tonic-gate 			 * Do the modification on the new one.
3540Sstevel@tonic-gate 			 */
3550Sstevel@tonic-gate 			p = malloc(len + 1 + data->d_size);
3560Sstevel@tonic-gate 			if (p == NULL) {
357*9131SRod.Evans@Sun.COM 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
358*9131SRod.Evans@Sun.COM 				    prog);
3598223SAli.Bahrami@Sun.COM 				mcs_exit(FAILURE);
3600Sstevel@tonic-gate 			}
3610Sstevel@tonic-gate 			(void) memcpy(p, data->d_buf, data->d_size);
3620Sstevel@tonic-gate 			(void) memcpy(&p[data->d_size], a_string, len + 1);
3630Sstevel@tonic-gate 			free(data->d_buf);
3640Sstevel@tonic-gate 			data->d_buf = p;
3650Sstevel@tonic-gate 			data->d_size = data->d_size + len + 1;
3660Sstevel@tonic-gate 		}
3670Sstevel@tonic-gate 	}
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate /*
3710Sstevel@tonic-gate  * ACT_COMPRESS
3720Sstevel@tonic-gate  */
3730Sstevel@tonic-gate #define	HALFLONG 16
3740Sstevel@tonic-gate #define	low(x)  (x&((1L<<HALFLONG)-1))
3750Sstevel@tonic-gate #define	high(x) (x>>HALFLONG)
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate static void
docompress(section_info_table * info)3780Sstevel@tonic-gate docompress(section_info_table *info)
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate 	Elf_Data *data;
3810Sstevel@tonic-gate 	size_t size;
3820Sstevel@tonic-gate 	char *buf;
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	if (info->mdata == 0) {
3850Sstevel@tonic-gate 		/*
3860Sstevel@tonic-gate 		 * mdata is not allocated yet.
3870Sstevel@tonic-gate 		 * Allocate the data and set it.
3880Sstevel@tonic-gate 		 */
3890Sstevel@tonic-gate 		char *p;
3900Sstevel@tonic-gate 		info->mdata = data = calloc(1, sizeof (Elf_Data));
3910Sstevel@tonic-gate 		if (data == NULL) {
392*9131SRod.Evans@Sun.COM 			error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
3938223SAli.Bahrami@Sun.COM 			mcs_exit(FAILURE);
3940Sstevel@tonic-gate 		}
3950Sstevel@tonic-gate 		*data = *info->data;
3960Sstevel@tonic-gate 		p = malloc(data->d_size);
3970Sstevel@tonic-gate 		(void) memcpy(p, (char *)data->d_buf, data->d_size);
3980Sstevel@tonic-gate 		data->d_buf = p;
3990Sstevel@tonic-gate 	}
4000Sstevel@tonic-gate 	size = info->mdata->d_size;
4010Sstevel@tonic-gate 	buf = (char *)info->mdata->d_buf;
4020Sstevel@tonic-gate 	buf = compress(buf, &size);
4030Sstevel@tonic-gate 	info->mdata->d_buf = buf;
4040Sstevel@tonic-gate 	info->mdata->d_size = size;
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate static char *
compress(char * str,size_t * size)4080Sstevel@tonic-gate compress(char *str, size_t *size)
4090Sstevel@tonic-gate {
4100Sstevel@tonic-gate 	int hash;
4110Sstevel@tonic-gate 	int i;
4120Sstevel@tonic-gate 	size_t temp_string_size = 0;
4130Sstevel@tonic-gate 	size_t o_size = *size;
4140Sstevel@tonic-gate 	char *temp_string = str;
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	int *hash_key;
4170Sstevel@tonic-gate 	size_t hash_num;
4180Sstevel@tonic-gate 	size_t hash_end;
4190Sstevel@tonic-gate 	size_t *hash_str;
4200Sstevel@tonic-gate 	char *strings;
4210Sstevel@tonic-gate 	size_t next_str;
4220Sstevel@tonic-gate 	size_t str_size;
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	hash_key = malloc(sizeof (int) * 200);
4250Sstevel@tonic-gate 	hash_end = 200;
4260Sstevel@tonic-gate 	hash_str = malloc(sizeof (size_t) * 200);
4270Sstevel@tonic-gate 	str_size = o_size+1;
4280Sstevel@tonic-gate 	strings = malloc(str_size);
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 	if (hash_key == NULL || hash_str == NULL || strings == NULL) {
431*9131SRod.Evans@Sun.COM 		error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
4320Sstevel@tonic-gate 		mcs_exit(FAILURE);
4330Sstevel@tonic-gate 	}
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	hash_num = 0;
4360Sstevel@tonic-gate 	next_str = 0;
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	while (temp_string_size < o_size)  {
4390Sstevel@tonic-gate 		size_t pos;
4400Sstevel@tonic-gate 		char c;
4410Sstevel@tonic-gate 		/*
4420Sstevel@tonic-gate 		 * Get a string
4430Sstevel@tonic-gate 		 */
4440Sstevel@tonic-gate 		pos = next_str;
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 		while ((c = *(temp_string++)) != '\0' &&
4470Sstevel@tonic-gate 		    (temp_string_size + (next_str - pos)) <= o_size) {
4480Sstevel@tonic-gate 			if (next_str >= str_size) {
4490Sstevel@tonic-gate 				str_size *= 2;
4500Sstevel@tonic-gate 				if ((strings = (char *)
4510Sstevel@tonic-gate 				    realloc(strings, str_size)) == NULL) {
452*9131SRod.Evans@Sun.COM 					error_message(MALLOC_ERROR, PLAIN_ERROR,
453*9131SRod.Evans@Sun.COM 					    NULL, prog);
4540Sstevel@tonic-gate 					mcs_exit(FAILURE);
4550Sstevel@tonic-gate 				}
4560Sstevel@tonic-gate 			}
4570Sstevel@tonic-gate 			strings[next_str++] = c;
4580Sstevel@tonic-gate 		}
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 		if (next_str >= str_size) {
4610Sstevel@tonic-gate 			str_size *= 2;
4620Sstevel@tonic-gate 			if ((strings = (char *)
4630Sstevel@tonic-gate 			    realloc(strings, str_size)) == NULL) {
464*9131SRod.Evans@Sun.COM 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
465*9131SRod.Evans@Sun.COM 				    prog);
4660Sstevel@tonic-gate 				mcs_exit(FAILURE);
4670Sstevel@tonic-gate 			}
4680Sstevel@tonic-gate 		}
4690Sstevel@tonic-gate 		strings[next_str++] = NULL;
4700Sstevel@tonic-gate 		/*
4710Sstevel@tonic-gate 		 * End get string
4720Sstevel@tonic-gate 		 */
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 		temp_string_size += (next_str - pos);
4750Sstevel@tonic-gate 		hash = dohash(pos + strings);
4760Sstevel@tonic-gate 		for (i = 0; i < hash_num; i++) {
4770Sstevel@tonic-gate 			if (hash != hash_key[i])
4780Sstevel@tonic-gate 				continue;
4790Sstevel@tonic-gate 			if (strcmp(pos + strings, hash_str[i] + strings) == 0)
4800Sstevel@tonic-gate 				break;
4810Sstevel@tonic-gate 		}
4820Sstevel@tonic-gate 		if (i != hash_num) {
4830Sstevel@tonic-gate 			next_str = pos;
4840Sstevel@tonic-gate 			continue;
4850Sstevel@tonic-gate 		}
4860Sstevel@tonic-gate 		if (hash_num == hash_end) {
4870Sstevel@tonic-gate 			hash_end *= 2;
4880Sstevel@tonic-gate 			hash_key = realloc((char *)hash_key,
4895154Sab196087 			    hash_end * sizeof (int));
4900Sstevel@tonic-gate 			hash_str = realloc((char *)hash_str,
4915154Sab196087 			    hash_end * sizeof (size_t));
4920Sstevel@tonic-gate 			if (hash_key == NULL || hash_str == NULL) {
493*9131SRod.Evans@Sun.COM 				error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
494*9131SRod.Evans@Sun.COM 				    prog);
4950Sstevel@tonic-gate 				mcs_exit(FAILURE);
4960Sstevel@tonic-gate 			}
4970Sstevel@tonic-gate 		}
4980Sstevel@tonic-gate 		hash_key[hash_num] = hash;
4990Sstevel@tonic-gate 		hash_str[hash_num++] = pos;
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	/*
5030Sstevel@tonic-gate 	 * Clean up
5040Sstevel@tonic-gate 	 */
5050Sstevel@tonic-gate 	free(hash_key);
5060Sstevel@tonic-gate 	free(hash_str);
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	/*
5090Sstevel@tonic-gate 	 * Return
5100Sstevel@tonic-gate 	 */
5110Sstevel@tonic-gate 	if (next_str != o_size) {
5120Sstevel@tonic-gate 		/*
5130Sstevel@tonic-gate 		 * string compressed.
5140Sstevel@tonic-gate 		 */
5150Sstevel@tonic-gate 		*size = next_str;
5160Sstevel@tonic-gate 		free(str);
5170Sstevel@tonic-gate 		str = malloc(next_str);
5180Sstevel@tonic-gate 		(void) memcpy(str, strings, next_str);
5190Sstevel@tonic-gate 	}
5200Sstevel@tonic-gate 	free(strings);
5210Sstevel@tonic-gate 	return (str);
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate static int
dohash(char * str)5250Sstevel@tonic-gate dohash(char *str)
5260Sstevel@tonic-gate {
5270Sstevel@tonic-gate 	long sum;
5280Sstevel@tonic-gate 	unsigned shift;
5290Sstevel@tonic-gate 	int t;
5300Sstevel@tonic-gate 	sum = 1;
5310Sstevel@tonic-gate 	for (shift = 0; (t = *str++) != NULL; shift += 7) {
5320Sstevel@tonic-gate 		sum += (long)t << (shift %= HALFLONG);
5330Sstevel@tonic-gate 	}
5340Sstevel@tonic-gate 	sum = low(sum) + high(sum);
5350Sstevel@tonic-gate 	/* LINTED */
5360Sstevel@tonic-gate 	return ((short)low(sum) + (short)high(sum));
5370Sstevel@tonic-gate }
538