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