4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright(c) 1988 AT&T
28 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
29 * Use is subject to license terms.
37 * Function prototypes.
39 static void docompress(section_info_table
*);
40 static char *compress(char *, size_t *);
41 static void doappend(char *, section_info_table
*);
42 static void doprint(char *, section_info_table
*);
43 static void dozap(section_info_table
*);
44 static int dohash(char *);
49 * Apply the actions specified by the user.
52 apply_action(section_info_table
*info
, char *cur_file
, Cmd_Info
*cmd_info
)
58 (void) gelf_getshdr(info
->scn
, &shdr
);
59 for (act_index
= 0; act_index
< actmax
; act_index
++) {
60 Action
[act_index
].a_cnt
++;
61 switch (Action
[act_index
].a_action
) {
63 if (GET_ACTION(info
->flags
) == ACT_DELETE
)
66 SET_ACTION(info
->flags
, ACT_ZAP
);
67 SET_MODIFIED(info
->flags
);
70 if (GET_ACTION(info
->flags
) == ACT_DELETE
)
72 if (shdr
.sh_type
== SHT_NOBITS
) {
73 error_message(ACT_PRINT_ERROR
, PLAIN_ERROR
,
74 NULL
, prog
, cur_file
, SECT_NAME
);
77 doprint(cur_file
, info
);
81 * If I am strip command, this is the
82 * only action I can take.
84 if (GET_ACTION(info
->flags
) == ACT_DELETE
)
86 if (GET_LOC(info
->flags
) == IN
) {
88 * If I am 'strip', I have to
89 * unset the candidate flag and
90 * unset the error return code.
92 if (CHK_OPT(info
, I_AM_STRIP
)) {
94 UNSET_CANDIDATE(info
->flags
);
96 char *name
= info
->name
;
100 name
= gettext("<unknown>");
101 error_message(ACT_DELETE1_ERROR
,
103 prog
, cur_file
, name
);
106 } else if (info
->rel_loc
== IN
) {
108 * If I am 'strip', I have to
109 * unset the candidate flag and
110 * unset the error return code.
112 if (CHK_OPT(info
, I_AM_STRIP
)) {
114 UNSET_CANDIDATE(info
->flags
);
117 error_message(ACT_DELETE2_ERROR
,
119 prog
, cur_file
, SECT_NAME
,
123 } else if (GET_LOC(info
->flags
) == PRIOR
) {
125 * I can not delete this
126 * section. I can only NULL
129 info
->secno
= (GElf_Word
)NULLED
;
130 (cmd_info
->no_of_nulled
)++;
132 info
->secno
= (GElf_Word
)DELETED
;
133 (cmd_info
->no_of_delete
)++;
135 SET_ACTION(info
->flags
, ACT_DELETE
);
136 SET_MODIFIED(info
->flags
);
139 if (shdr
.sh_type
== SHT_NOBITS
) {
141 error_message(ACT_APPEND1_ERROR
, PLAIN_ERROR
,
142 NULL
, prog
, cur_file
, SECT_NAME
);
144 } else if (GET_LOC(info
->flags
) == IN
) {
146 error_message(ACT_APPEND2_ERROR
, PLAIN_ERROR
,
147 NULL
, prog
, cur_file
, SECT_NAME
);
150 doappend(Action
[act_index
].a_string
, info
);
151 (cmd_info
->no_of_append
)++;
152 info
->secno
= info
->osecno
;
153 SET_ACTION(info
->flags
, ACT_APPEND
);
154 SET_MODIFIED(info
->flags
);
155 if (GET_LOC(info
->flags
) == PRIOR
)
156 info
->secno
= (GElf_Word
)EXPANDED
;
160 * If this section is already deleted,
163 if (GET_ACTION(info
->flags
) == ACT_DELETE
)
165 if (shdr
.sh_type
== SHT_NOBITS
) {
167 error_message(ACT_COMPRESS1_ERROR
, PLAIN_ERROR
,
168 NULL
, prog
, cur_file
, SECT_NAME
);
170 } else if (GET_LOC(info
->flags
) == IN
) {
172 error_message(ACT_COMPRESS2_ERROR
, PLAIN_ERROR
,
173 NULL
, prog
, cur_file
, SECT_NAME
);
178 (cmd_info
->no_of_compressed
)++;
179 SET_ACTION(info
->flags
, ACT_COMPRESS
);
180 SET_MODIFIED(info
->flags
);
181 if (GET_LOC(info
->flags
) == PRIOR
)
182 info
->secno
= (GElf_Word
)SHRUNK
;
193 dozap(section_info_table
*info
)
197 info
->mdata
= data
= malloc(sizeof (Elf_Data
));
199 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
, prog
);
203 data
->d_buf
= calloc(1, data
->d_size
);
204 if (data
->d_buf
== NULL
) {
205 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
, prog
);
214 doprint(char *cur_file
, section_info_table
*info
)
220 if (GET_MODIFIED(info
->flags
) == 0)
227 temp_size
= data
->d_size
;
228 temp_string
= data
->d_buf
;
232 (void) fprintf(stdout
, "%s:\n", cur_file
);
234 while (temp_size
--) {
235 char c
= *temp_string
++;
238 (void) putchar('\n');
245 (void) putchar('\n');
252 doappend(char *a_string
, section_info_table
*info
)
260 * Get the length of the string to be added. We accept any
261 * string (even null), as this is arbitrary user defined text.
263 * The caller expects this routine to replace a NULL info->mdata
264 * field with a pointer to a freshly allocated copy. Any attempt
265 * to optimize away a null string append would have to deal with
266 * that, as failing to do so will cause a segfault when the NULL
267 * mdata field is dereferenced. Accepting null strings in
268 * this very unimportant case eliminates the need for that.
270 len
= strlen(a_string
);
273 * Every modification operation will be done
274 * to a new Elf_Data descriptor.
276 if (info
->mdata
== 0) {
278 * mdata is not allocated yet.
279 * Allocate the data and set it.
281 info
->mdata
= data
= calloc(1, sizeof (Elf_Data
));
283 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
, prog
);
289 * Check if the section is deleted or not.
290 * Or if the size is 0 or not.
292 if ((GET_ACTION(info
->flags
) == ACT_DELETE
) ||
295 * The section was deleated.
296 * But now, the user wants to add data to this
299 data
->d_buf
= calloc(1, len
+ 2);
300 if (data
->d_buf
== NULL
) {
301 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
,
305 tp
= (char *)data
->d_buf
;
306 (void) memcpy(& tp
[1], a_string
, len
+ 1);
307 data
->d_size
= len
+ 2;
310 * The user wants to add data to the section.
311 * I am not going to change the original data.
312 * Do the modification on the new one.
314 p
= malloc(len
+ 1 + data
->d_size
);
316 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
,
320 (void) memcpy(p
, data
->d_buf
, data
->d_size
);
321 (void) memcpy(&p
[data
->d_size
], a_string
, len
+ 1);
323 data
->d_size
= data
->d_size
+ len
+ 1;
327 * mdata is already allocated.
331 if ((GET_ACTION(info
->flags
) == ACT_DELETE
) ||
334 * The section was deleated.
335 * But now, the user wants to add data to this
340 data
->d_buf
= calloc(1, len
+ 2);
341 if (data
->d_buf
== NULL
) {
342 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
,
346 tp
= (char *)data
->d_buf
;
347 (void) memcpy(&tp
[1], a_string
, len
+ 1);
348 data
->d_size
= len
+ 2;
351 * The user wants to add data to the section.
352 * I am not going to change the original data.
353 * Do the modification on the new one.
355 p
= malloc(len
+ 1 + data
->d_size
);
357 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
,
361 (void) memcpy(p
, data
->d_buf
, data
->d_size
);
362 (void) memcpy(&p
[data
->d_size
], a_string
, len
+ 1);
365 data
->d_size
= data
->d_size
+ len
+ 1;
374 #define low(x) (x&((1L<<HALFLONG)-1))
375 #define high(x) (x>>HALFLONG)
378 docompress(section_info_table
*info
)
384 if (info
->mdata
== 0) {
386 * mdata is not allocated yet.
387 * Allocate the data and set it.
390 info
->mdata
= data
= calloc(1, sizeof (Elf_Data
));
392 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
, prog
);
396 p
= malloc(data
->d_size
);
397 (void) memcpy(p
, (char *)data
->d_buf
, data
->d_size
);
400 size
= info
->mdata
->d_size
;
401 buf
= (char *)info
->mdata
->d_buf
;
402 buf
= compress(buf
, &size
);
403 info
->mdata
->d_buf
= buf
;
404 info
->mdata
->d_size
= size
;
408 compress(char *str
, size_t *size
)
412 size_t temp_string_size
= 0;
413 size_t o_size
= *size
;
414 char *temp_string
= str
;
424 hash_key
= malloc(sizeof (int) * 200);
426 hash_str
= malloc(sizeof (size_t) * 200);
428 strings
= malloc(str_size
);
430 if (hash_key
== NULL
|| hash_str
== NULL
|| strings
== NULL
) {
431 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
, prog
);
438 while (temp_string_size
< o_size
) {
446 while ((c
= *(temp_string
++)) != '\0' &&
447 (temp_string_size
+ (next_str
- pos
)) <= o_size
) {
448 if (next_str
>= str_size
) {
450 if ((strings
= (char *)
451 realloc(strings
, str_size
)) == NULL
) {
452 error_message(MALLOC_ERROR
, PLAIN_ERROR
,
457 strings
[next_str
++] = c
;
460 if (next_str
>= str_size
) {
462 if ((strings
= (char *)
463 realloc(strings
, str_size
)) == NULL
) {
464 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
,
469 strings
[next_str
++] = NULL
;
474 temp_string_size
+= (next_str
- pos
);
475 hash
= dohash(pos
+ strings
);
476 for (i
= 0; i
< hash_num
; i
++) {
477 if (hash
!= hash_key
[i
])
479 if (strcmp(pos
+ strings
, hash_str
[i
] + strings
) == 0)
486 if (hash_num
== hash_end
) {
488 hash_key
= realloc((char *)hash_key
,
489 hash_end
* sizeof (int));
490 hash_str
= realloc((char *)hash_str
,
491 hash_end
* sizeof (size_t));
492 if (hash_key
== NULL
|| hash_str
== NULL
) {
493 error_message(MALLOC_ERROR
, PLAIN_ERROR
, NULL
,
498 hash_key
[hash_num
] = hash
;
499 hash_str
[hash_num
++] = pos
;
511 if (next_str
!= o_size
) {
517 str
= malloc(next_str
);
518 (void) memcpy(str
, strings
, next_str
);
531 for (shift
= 0; (t
= *str
++) != NULL
; shift
+= 7) {
532 sum
+= (long)t
<< (shift
%= HALFLONG
);
534 sum
= low(sum
) + high(sum
);
536 return ((short)low(sum
) + (short)high(sum
));