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