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 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
32 * Copyright (c) 1987, 1988 Microsoft Corporation
37 * Copyright (c) 1979 Regents of the University of California
40 #pragma ident "%Z%%M% %I% %E% SMI"
52 #include <sys/types.h>
66 /* used to maintain a list of program sections to look in */
67 typedef struct sec_name
{
69 struct sec_name
*next
;
76 static void find(long);
77 static int ismagic(int, struct aexec
*, FILE *);
78 static int tryelf(FILE *);
79 static int dirt(int, int);
83 * Strings - extract strings from an object file for whatever
85 * The algorithm is to look for sequences of "non-junk" characters
86 * The variable "minlen" is the minimum length string printed.
87 * This helps get rid of garbage.
88 * Default minimum string length is 4 characters.
92 #define DEF_MIN_STRING 4
97 static int minlength
= 0;
98 static int isClocale
= 0;
99 static char *buf
= NULL
;
100 static char *tbuf
= NULL
;
101 static size_t buf_size
= 0;
102 static int rc
= 0; /* exit code */
105 * Returns 0 when sections have been successfully looked through,
106 * otherwise returns 1.
109 look_in_sections(char *file
, sec_name_t
*seclistptr
)
111 int fd
= fileno(stdin
);
119 (void) lseek(fd
, 0L, 0);
120 elf
= elf_begin(fd
, ELF_C_READ
, NULL
);
121 if (gelf_getehdr(elf
, &ehdr
) == (GElf_Ehdr
*)NULL
) {
122 (void) fprintf(stderr
, "%s: %s\n", file
, elf_errmsg(-1));
127 while ((scn
= elf_nextscn(elf
, scn
)) != 0) {
129 if (gelf_getshdr(scn
, &shdr
) == (GElf_Shdr
*)0) {
130 (void) fprintf(stderr
, "%s: %s\n", file
,
136 if (seclistptr
!= NULL
) {
139 /* Only look in the specified section(s). */
140 if ((scn_name
= elf_strptr(elf
, ehdr
.e_shstrndx
,
141 (size_t)shdr
.sh_name
)) == NULL
) {
142 (void) fprintf(stderr
, "%s: %s\n", file
,
149 for (sptr
= seclistptr
; sptr
!= NULL
;
151 if (strcmp(scn_name
, sptr
->name
) == 0) {
159 * Look through program sections that are
162 if ((shdr
.sh_flags
& SHF_ALLOC
) &&
163 (shdr
.sh_type
== SHT_PROGBITS
)) {
167 if (found_sec
== 1) {
168 (void) fseek(stdin
, (long)shdr
.sh_offset
, 0);
169 find((long)shdr
.sh_size
);
185 sec_name_t
*seclistptr
= NULL
;
186 sec_name_t
*seclistendptr
;
189 (void) setlocale(LC_ALL
, "");
191 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
192 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
194 (void) textdomain(TEXT_DOMAIN
);
196 locale
= setlocale(LC_CTYPE
, NULL
);
197 if ((strcmp(locale
, "C") == 0) ||
198 (strcmp(locale
, "POSIX") == 0)) {
202 /* check for non-standard "-" option */
203 for (i
= 1; i
< argc
; i
++) {
204 if (strcmp(argv
[i
], "-") == 0) {
215 while ((opt
= getopt(argc
, argv
, "1234567890an:N:ot:")) != -1) {
222 minlength
= (int)strtol(optarg
, (char **)NULL
,
227 if (((sptr
= malloc(sizeof (sec_name_t
)))
228 == NULL
) || ((sptr
->name
= strdup(optarg
))
230 (void) fprintf(stderr
, gettext(
231 "Cannot allocate memory: "
232 "%s\n"), strerror(errno
));
235 if (seclistptr
== NULL
) {
237 seclistptr
->next
= NULL
;
238 seclistendptr
= sptr
;
240 seclistendptr
->next
= sptr
;
241 seclistendptr
= sptr
;
253 if (t_format
!= 'd' && t_format
!= 'o' &&
256 (void) fprintf(stderr
,
257 gettext("Invalid format\n"));
272 minlength
+= opt
- '0';
280 /* if min string not specified, use default */
282 minlength
= DEF_MIN_STRING
;
285 /* dynamic allocation of char buffer array */
286 buf
= (char *)malloc(BUFSIZ
);
288 (void) fprintf(stderr
, gettext("Cannot allocate memory: %s\n"),
296 /* for each file operand */
298 if (argv
[optind
] != NULL
) {
299 if (freopen(argv
[optind
], "r", stdin
) == NULL
) {
300 perror(argv
[optind
]);
312 hsize
= fread((char *)&ahdr
, sizeof (char),
313 sizeof (ahdr
), stdin
);
314 htype
= ismagic(hsize
, &ahdr
, stdin
);
318 (void) fseek(stdin
, (long)ADATAPOS(&ahdr
), 0);
319 find((long)ahdr
.xa_data
);
324 * Will take care of COFF M32 and i386 also
325 * As well as ELF M32, i386 and Sparc (32-
328 rc
= look_in_sections(argv
[optind
- 1],
335 (void) fseek(stdin
, (long)0, 0);
339 } while (argv
[optind
] != NULL
);
353 for (c
= ~EOF
; (cnt
> 0) && (c
!= EOF
); cnt
--) {
355 if (!(cr
= dirt(c
, cc
))) {
356 if (cc
>= minlength
) {
360 (void) printf("%7ld ",
361 ftell(stdin
) - cc
- 1);
365 (void) printf("%7lo ",
366 ftell(stdin
) - cc
- 1);
370 (void) printf("%7lx ",
371 ftell(stdin
) - cc
- 1);
377 buf
[buf_size
-1] = '\0';
393 char mbuf
[MB_LEN_MAX
+ 1];
401 * If character count is greater than dynamic
402 * char buffer size, then increase char buffer size.
404 if (cc
>= (buf_size
-2)) {
407 tbuf
= (char *)realloc(buf
, buf_size
);
409 (void) fprintf(stderr
,
410 gettext("Cannot allocate memory: %s\n"),
433 for (len
= 1; len
< (unsigned int)MB_CUR_MAX
; len
++) {
435 (mbuf
[len
] = getc(stdin
)) == -1)
440 if ((len1
= mbtowc(&wc
, mbuf
, len
)) <= 0) {
446 if ((cc
+ len1
) >= (buf_size
-2)) {
449 tbuf
= (char *)realloc(buf
, buf_size
);
451 (void) fprintf(stderr
,
452 gettext("Cannot allocate memory: %s\n"),
463 for (i
= 0; i
< len1
; i
++, cc
++)
469 for (len
--; len
>= len1
; len
--)
470 (void) ungetc(mbuf
[len
], stdin
);
476 ismagic(hsize
, hdr
, fp
)
481 switch (hdr
->xa_magic
) {
486 if (hsize
< sizeof (struct aexec
))
507 if ((elf_version(EV_CURRENT
)) == EV_NONE
) {
508 (void) fprintf(stderr
, "%s\n", elf_errmsg(-1));
512 (void) lseek(fd
, 0L, 0);
514 if ((elf
= elf_begin(fd
, ELF_C_READ
, NULL
)) == NULL
) {
515 (void) fprintf(stderr
, "%s\n", elf_errmsg(-1));
519 switch (elf_kind(elf
)) {
522 * This should try to run strings on each element
523 * of the archive. For now, just search entire
524 * file (-a), as strings has always done
532 if (gelf_getehdr(elf
, &ehdr
) == (GElf_Ehdr
*)NULL
) {
533 (void) fprintf(stderr
, "%s\n", elf_errmsg(-1));
538 if ((ehdr
.e_type
== ET_CORE
) || (ehdr
.e_type
== ET_NONE
)) {
553 (void) fprintf(stderr
, gettext(
554 "Usage: strings [-a | -] [-t format | -o] [-n number | -number]"
555 "\n\t[-N name] [file]...\n"));