425 lines
7.6 KiB
C
Executable File
425 lines
7.6 KiB
C
Executable File
/*
|
|
* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
|
|
* All Rights Reserved
|
|
*/
|
|
|
|
/*
|
|
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
|
|
* The copyright notice above does not evidence any
|
|
* actual or intended publication of such source code.
|
|
*/
|
|
|
|
#ident "@(#)strings.c 1.9 95/02/24 SMI" /* SVr4.0 1.3 */
|
|
/*
|
|
* Copyright (c) 1987, 1988 Microsoft Corporation
|
|
* All Rights Reserved
|
|
*/
|
|
|
|
/*
|
|
* This Module contains Proprietary Information of Microsoft
|
|
* Corporation and should be treated as Confidential.
|
|
*/
|
|
|
|
|
|
/*
|
|
* @(#) strings.c 1.3 88/05/09 strings:strings.c
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 1979 Regents of the University of California
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include "x.out.h"
|
|
#include <ctype.h>
|
|
#include <libelf.h>
|
|
#include <sys/elf.h>
|
|
#include <locale.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
|
|
#define NOTOUT 0
|
|
#define AOUT 1
|
|
#define BOUT 2
|
|
#define XOUT 3
|
|
#define ELF 4
|
|
|
|
#define dirt(c) ((!isascii(c) || !isprint(c)) && (isClocale || isnssx(c)))
|
|
|
|
|
|
/* struct exec header */
|
|
static union uexec {
|
|
struct xexec u_xhdr; /* x.out */
|
|
struct aexec u_ahdr; /* a.out */
|
|
struct bexec u_bhdr; /* b.out */
|
|
} header;
|
|
|
|
|
|
/*
|
|
* function prototypes
|
|
*/
|
|
static void Usage();
|
|
static void find(long);
|
|
static int ismagic(int, union uexec *, FILE *);
|
|
static int tryelf(FILE *);
|
|
static int isnssx(int);
|
|
|
|
|
|
/*
|
|
* Strings - extract strings from an object file for whatever
|
|
*
|
|
* The algorithm is to look for sequences of "non-junk" characters
|
|
* The variable "minlen" is the minimum length string printed.
|
|
* This helps get rid of garbage.
|
|
* Default minimum string length is 4 characters.
|
|
*
|
|
*/
|
|
|
|
static struct xexec *xhdrp = &(header.u_xhdr);
|
|
static struct aexec *ahdrp = &(header.u_ahdr);
|
|
static struct bexec *bhdrp = &(header.u_bhdr);
|
|
|
|
#define DEF_MIN_STRING 4
|
|
|
|
static int tflg;
|
|
static char t_format;
|
|
static int aflg;
|
|
static int minlength = 0;
|
|
static int isClocale;
|
|
|
|
|
|
main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
int hsize;
|
|
int htype;
|
|
int fd;
|
|
Elf *elf;
|
|
Elf32_Ehdr *ehdr;
|
|
Elf_Scn *scn;
|
|
Elf32_Shdr *shdr;
|
|
char *scn_name;
|
|
char *locale;
|
|
int opt;
|
|
int i;
|
|
|
|
|
|
(void) setlocale(LC_ALL, "");
|
|
|
|
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
|
|
#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
|
|
#endif
|
|
(void) textdomain(TEXT_DOMAIN);
|
|
|
|
locale = setlocale(LC_CTYPE, NULL);
|
|
isClocale = (strcmp(locale, "C") == 0) ||
|
|
(strcmp(locale, "POSIX") == 0) ||
|
|
(strcmp(locale, "en_US") == 0);
|
|
|
|
/* check for non-standard "-" option */
|
|
for (i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "-") == 0) {
|
|
aflg++;
|
|
while (i < argc) {
|
|
argv[i] = argv[i+1];
|
|
i++;
|
|
}
|
|
argc--;
|
|
}
|
|
}
|
|
|
|
/* get options */
|
|
while ((opt = getopt(argc, argv, "1234567890an:ot:")) != -1) {
|
|
switch (opt) {
|
|
case 'a':
|
|
aflg++;
|
|
break;
|
|
|
|
case 'n':
|
|
minlength = (int) strtol(optarg, (char **)NULL,
|
|
10);
|
|
break;
|
|
|
|
case 'o':
|
|
tflg++;
|
|
t_format = 'd';
|
|
break;
|
|
|
|
case 't':
|
|
tflg++;
|
|
t_format = *optarg;
|
|
if (t_format != 'd' && t_format != 'o' &&
|
|
t_format != 'x')
|
|
{
|
|
(void) fprintf(stderr,
|
|
gettext("Invalid format\n"));
|
|
Usage();
|
|
}
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
minlength *= 10;
|
|
minlength += opt - '0';
|
|
break;
|
|
|
|
default:
|
|
Usage();
|
|
}
|
|
}
|
|
|
|
/* if min string not specified, use default */
|
|
if (!minlength)
|
|
minlength = DEF_MIN_STRING;
|
|
|
|
/* for each file operand */
|
|
do {
|
|
if (argv[optind] != NULL) {
|
|
if (freopen(argv[optind], "r", stdin) == NULL) {
|
|
perror(argv[optind]);
|
|
exit(1);
|
|
}
|
|
optind++;
|
|
} else
|
|
aflg++;
|
|
|
|
if (aflg)
|
|
htype = NOTOUT;
|
|
else {
|
|
hsize = fread((char *) &header, sizeof (char),
|
|
sizeof (header), stdin);
|
|
htype = ismagic(hsize, &header, stdin);
|
|
}
|
|
switch (htype) {
|
|
case AOUT:
|
|
(void) fseek(stdin, (long) ADATAPOS(ahdrp), 0);
|
|
find((long) ahdrp->xa_data);
|
|
continue;
|
|
|
|
case BOUT:
|
|
(void) fseek(stdin, (long) BDATAPOS(bhdrp), 0);
|
|
find((long) bhdrp->xb_data);
|
|
continue;
|
|
|
|
case XOUT:
|
|
(void) fseek(stdin, (long) XDATAPOS(xhdrp), 0);
|
|
find((long) xhdrp->x_data);
|
|
continue;
|
|
|
|
case ELF:
|
|
/*
|
|
* Will take care of COFF M32 and i386 also
|
|
* As well as ELF M32, i386 and Sparc
|
|
*/
|
|
|
|
fd = fileno(stdin);
|
|
(void) lseek(fd, 0L, 0);
|
|
elf = elf_begin(fd, ELF_C_READ, NULL);
|
|
ehdr = elf32_getehdr(elf);
|
|
scn = 0;
|
|
while ((scn = elf_nextscn(elf, scn)) != 0)
|
|
{
|
|
if ((shdr = elf32_getshdr(scn)) != 0)
|
|
scn_name = elf_strptr(elf,
|
|
ehdr->e_shstrndx,
|
|
(size_t)shdr->sh_name);
|
|
/*
|
|
* There is more than one .data section
|
|
*/
|
|
|
|
if ((strcmp(scn_name, ".rodata")
|
|
== 0) ||
|
|
(strcmp(scn_name, ".rodata1")
|
|
== 0) ||
|
|
(strcmp(scn_name, ".data")
|
|
== 0) ||
|
|
(strcmp(scn_name, ".data1")
|
|
== 0))
|
|
{
|
|
(void) fseek(stdin,
|
|
(long) shdr->sh_offset, 0);
|
|
find((long) shdr->sh_size);
|
|
}
|
|
}
|
|
continue;
|
|
|
|
case NOTOUT:
|
|
default:
|
|
(void) fseek(stdin, (long) 0, 0);
|
|
find((long) 100000000L);
|
|
continue;
|
|
}
|
|
} while (argv[optind] != NULL);
|
|
|
|
return (0);
|
|
}
|
|
|
|
|
|
static void
|
|
find(cnt)
|
|
long cnt;
|
|
{
|
|
static char buf[BUFSIZ];
|
|
int c;
|
|
int cc;
|
|
|
|
cc = 0;
|
|
for (c = ~EOF; (cnt > 0) && (c != EOF); cnt--) {
|
|
c = getc(stdin);
|
|
if (dirt(c)) {
|
|
if (cc >= minlength) {
|
|
if (tflg) {
|
|
switch (t_format) {
|
|
case 'd':
|
|
(void) printf("%7ld ",
|
|
ftell(stdin) - cc - 1);
|
|
break;
|
|
|
|
case 'o':
|
|
(void) printf("%7lo ",
|
|
ftell(stdin) - cc - 1);
|
|
break;
|
|
|
|
case 'x':
|
|
(void) printf("%7lx ",
|
|
ftell(stdin) - cc - 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
buf[cc] = '\0';
|
|
(void) puts(buf);
|
|
}
|
|
cc = 0;
|
|
} else if (cc < (BUFSIZ - 2))
|
|
buf[cc++] = (char) c;
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
ismagic(hsize, hdr, fp)
|
|
int hsize;
|
|
union uexec *hdr;
|
|
FILE *fp;
|
|
{
|
|
switch ((int) (hdr->u_bhdr.xb_magic)) {
|
|
case A_MAGIC1:
|
|
case A_MAGIC2:
|
|
case A_MAGIC3:
|
|
case A_MAGIC4:
|
|
if (hsize < sizeof (struct bexec))
|
|
return (NOTOUT);
|
|
else
|
|
return (BOUT);
|
|
default:
|
|
break;
|
|
}
|
|
switch (hdr->u_xhdr.x_magic) {
|
|
case X_MAGIC:
|
|
if (hsize < sizeof (struct xexec))
|
|
return (NOTOUT);
|
|
else
|
|
return (XOUT);
|
|
default:
|
|
break;
|
|
}
|
|
switch (hdr->u_ahdr.xa_magic) {
|
|
case A_MAGIC1:
|
|
case A_MAGIC2:
|
|
case A_MAGIC3:
|
|
case A_MAGIC4:
|
|
if (hsize < sizeof (struct aexec))
|
|
return (NOTOUT);
|
|
else
|
|
return (AOUT);
|
|
default:
|
|
break;
|
|
}
|
|
return (tryelf(fp));
|
|
}
|
|
|
|
|
|
static int
|
|
tryelf(fp)
|
|
FILE *fp;
|
|
{
|
|
int fd;
|
|
Elf *elf;
|
|
Elf32_Ehdr *ehdr;
|
|
|
|
fd = fileno(fp);
|
|
|
|
if ((elf_version(EV_CURRENT)) == EV_NONE) {
|
|
(void) fprintf(stderr, "%s\n", gettext(elf_errmsg(-1)));
|
|
return (NOTOUT);
|
|
}
|
|
|
|
(void) lseek(fd, 0L, 0);
|
|
|
|
if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
|
|
(void) fprintf(stderr, "%s\n", gettext(elf_errmsg(-1)));
|
|
return (NOTOUT);
|
|
}
|
|
|
|
if ((elf_kind(elf)) == ELF_K_NONE) {
|
|
(void) elf_end(elf);
|
|
return (NOTOUT);
|
|
}
|
|
|
|
if ((ehdr = elf32_getehdr(elf)) == NULL) {
|
|
(void) fprintf(stderr, "%s\n", gettext(elf_errmsg(-1)));
|
|
(void) elf_end(elf);
|
|
return (NOTOUT);
|
|
}
|
|
|
|
if ((ehdr->e_type == ET_CORE) || (ehdr->e_type == ET_NONE)) {
|
|
(void) elf_end(elf);
|
|
return (NOTOUT);
|
|
}
|
|
|
|
(void) elf_end(elf);
|
|
|
|
return (ELF);
|
|
|
|
}
|
|
|
|
|
|
static int
|
|
isnssx(c)
|
|
int c;
|
|
{
|
|
switch (c) {
|
|
case 0216: /* SS2 */
|
|
case 0217: /* SS3 */
|
|
return (0);
|
|
case 0240:
|
|
case 0377:
|
|
return (1);
|
|
default:
|
|
return (c < ' ' || (c >= 0200 && c <= 0237));
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
Usage()
|
|
{
|
|
(void) fprintf(stderr, gettext(
|
|
"Usage: strings [-|-a] [-t format] [-n #] [file ...]\n"
|
|
" strings [-|-a] [-o] [-#] [file ...]\n"));
|
|
exit(1);
|
|
}
|