From: <jk...@us...> - 2008-04-02 09:44:30
|
Revision: 3 http://elftoolchain.svn.sourceforge.net/elftoolchain/?rev=3&view=rev Author: jkoshy Date: 2008-04-02 02:44:26 -0700 (Wed, 02 Apr 2008) Log Message: ----------- Add an implementation of strings(1) contributed by Sam Arun Raj. Added Paths: ----------- projects/strings/trunk/Makefile projects/strings/trunk/strings.1 projects/strings/trunk/strings.c Added: projects/strings/trunk/Makefile =================================================================== --- projects/strings/trunk/Makefile (rev 0) +++ projects/strings/trunk/Makefile 2008-04-02 09:44:26 UTC (rev 3) @@ -0,0 +1,8 @@ +# + +PROG= strings +WARNS?= 6 +LDADD= -lelf + +.include <bsd.prog.mk> + Added: projects/strings/trunk/strings.1 =================================================================== --- projects/strings/trunk/strings.1 (rev 0) +++ projects/strings/trunk/strings.1 2008-04-02 09:44:26 UTC (rev 3) @@ -0,0 +1,141 @@ +.\" Copyright (c) 2007 S.Sam Arun Raj +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd April 15, 2007 +.Dt STRINGS 1 +.Os +.Sh NAME +.Nm strings +.Nd "print the strings of printable characters in files" +.Sh SYNOPSIS +.Nm +.Op Fl afho +.Op Fl e Ar encoding +.Op Fl n Ar number +.Op Fl t Ar radix +.Op Ar +.Sh DESCRIPTION +Fo each +.Ar file +given, the +.Nm +utility prints any contiguous seqeunce of printable +characters of atleast 'n' characters long (the default is 4 characters) +followed by an unprintable character. +.Nm +only scans the initialized and loaded sections of ELF objects; for other +file types, the entire file is scanned. +The +.Nm +utility is mainly useful for determining the contents of non-text files. +.Pp +If no file name is specified in the input, standard input is read from. +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl a +This option instructs +.Nm +to scan the entire file. This is useful to override the default behaviour of +scanning only initialized and loaded section of ELF objects. +.It Fl e Ar encoding +Select the character encoding to be used while searching for strings. +The encoding depends on the single character argument which speicifes +the encoding; +.Ar s +for single 7-bit-byte characters (ASCII, ISO 8859, etc., default). +.Ar S +for single 8-bit-byte characters. +.Ar l +for 16-bit littleendian. +.Ar b +for 16-bit bigendian. +.Ar L +for 32-bit littleendian. +.Ar B +for 32-bit bigendian. +.It Fl f +Print the name of the file before each string. +.It Fl t Ar radix +Print the offset from the start of the file before each string. The +format depends on the single character argument which specifies the +radix of the offset; +.Ar d +for decimal, +.Ar o +for octal, +.Ar x +for hexadecimal. +.It Fl n Ar number +Print the contiguous character sequence of alteast +.Ar number +characters long, instead of default 4 characters. +.It Fl o +This is same as -t o. +.It Fl h +This prints a usage summary and exits. +.El +.Sh EXIT STATUS +.Ex -std +.Sh EXAMPLES +The following are examples of typical usage +of the +.Nm +command: +.Dl "" +.Dl "$ strings /bin/ls" +.Dl "$ strings -a /bin/ln" +.Dl "$ strings -a -f -t x /bin/cat" +.Sh SEE ALSO +.Xr ar 1 , +.Xr nm 1 , +.Xr objdump 1 , +.Xr ranlib , +.Xr readelf 1 +.Sh HISTORY +The first FreeBSD +.Nm +utility appeared in +.Fx v3. +It was later discontinued in +.Fx v5 , +when i386-only a.out format was dropped in favor of ELF. +.Sh AUTHORS +.An -nosplit +The +.Nm +utility was re-written by +.An S.Sam Arun Raj Aq sam...@gm... +This manual page was written by +.An S.Sam Arun Raj Aq sam...@gm... +.Sh LIMITATIONS +Unlike the GNU +.Nm +this doesn't support multiple object file formats, only ELF using the +.Xr elf 3 +and +.Xr gelf 3 +API's. Added: projects/strings/trunk/strings.c =================================================================== --- projects/strings/trunk/strings.c (rev 0) +++ projects/strings/trunk/strings.c 2008-04-02 09:44:26 UTC (rev 3) @@ -0,0 +1,411 @@ +/*- + * Copyright (c) 2007 S.Sam Arun Raj + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/stat.h> +#include <sys/types.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <getopt.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sysexits.h> +#include <unistd.h> + +#include <libelf.h> +#include <gelf.h> + +enum radix_style { + RADIX_DECIMAL, + RADIX_HEX, + RADIX_OCTAL +}; + +enum encoding_style { + ENCODING_7BIT, + ENCODING_8BIT, + ENCODING_16BIT_BIG, + ENCODING_16BIT_LITTLE, + ENCODING_32BIT_BIG, + ENCODING_32BIT_LITTLE +}; + +#define PRINTABLE(c) \ + ((c) >= 0 && (c) <= 255 && \ + ((c) == '\t' || isprint((c)) || \ + (encoding == ENCODING_8BIT && (c) > 127))) + + +int encoding_size, entire_file, min_len, show_filename, show_loc; +enum encoding_style encoding; +enum radix_style radix; + +long getcharacter(void); +int handle_file(const char *); +int handle_elf(const char *, int); +int handle_binary(const char *, int); +int find_strings(const char *, off_t, off_t); +void usage(void); + +/* + * strings(1) extracts text(contiguous printable characters) + * from elf and binary files. + */ +int +main(int argc, char **argv) +{ + int ch, rc; + + rc = EX_OK; + min_len = 0; + encoding_size = 1; + if (elf_version(EV_CURRENT) == EV_NONE) + errx(EX_SOFTWARE, "ELF library initialization failed: %s", + elf_errmsg(-1)); + + while ((ch = getopt(argc, argv, "1234567890ae:fhn:ot:")) != -1) + switch((char)ch) { + case 'a': + entire_file = 1; + break; + case 'e': + if (*optarg == 's') { + encoding = ENCODING_7BIT; + } else if (*optarg == 'S') { + encoding = ENCODING_8BIT; + } else if (*optarg == 'b') { + encoding = ENCODING_16BIT_BIG; + encoding_size = 2; + } else if (*optarg == 'B') { + encoding = ENCODING_32BIT_BIG; + encoding_size = 4; + } else if (*optarg == 'l') { + encoding = ENCODING_16BIT_LITTLE; + encoding_size = 2; + } else if (*optarg == 'L') { + encoding = ENCODING_32BIT_LITTLE; + encoding_size = 4; + } else + usage(); + /* NOTREACHED */ + break; + case 'f': + show_filename = 1; + break; + case 'n': + min_len = (int)strtoimax(optarg, (char**)NULL, 10); + break; + case 'o': + show_loc = 1; + radix = RADIX_OCTAL; + break; + case 't': + show_loc = 1; + if (*optarg == 'd') + radix = RADIX_DECIMAL; + else if (*optarg == 'o') + radix = RADIX_OCTAL; + else if (*optarg == 'x') + radix = RADIX_HEX; + else + usage(); + /* NOTREACHED */ + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + min_len *= 10; + min_len += ch - '0'; + break; + case 'h': + case '?': + default: + usage(); + /* NOTREACHED */ + } + argc -= optind; + argv += optind; + + if (!min_len) + min_len = 4; + if (!*argv) + rc = handle_file("{standard input}"); + else while (*argv) { + rc = handle_file(*argv); + argv++; + } + return(rc); +} + +int +handle_file(const char *name) +{ + int fd, rt; + + if (name == NULL) + return(EX_NOINPUT); + if (strcmp("{standard input}", name) != 0) { + if (freopen(name, "rb", stdin) == NULL) { + warnx("'%s': %s", name, strerror(errno)); + return(EX_NOINPUT); + } + } else { + return find_strings(name, (off_t)0, (off_t)0); + } + + fd = fileno(stdin); + if (fd < 0) + return(EX_NOINPUT); + rt = handle_elf(name, fd); + return(rt); +} + +/* + * Files not understood by handle_elf, will be passed off here and will + * treated as a binary file. This would include text file, core dumps ... + */ +int +handle_binary(const char *name, int fd) +{ + struct stat buf; + + memset(&buf, 0, sizeof(struct stat)); + (void) lseek(fd, (off_t)0, SEEK_SET); + if (!fstat(fd, &buf)) + return find_strings(name, (off_t)0, buf.st_size); + return(EX_SOFTWARE); +} + +/* + * Will analyse a file to see if it ELF, other files including ar(1), + * core dumps are passed off and treated as flat binary files. Unlike + * GNU size in FreeBSD this routine will not treat ELF object from + * different archs as flat binary files(has to overridden using -a). + */ +int +handle_elf(const char *name, int fd) +{ + GElf_Ehdr elfhdr; + GElf_Shdr shdr; + Elf *elf; + Elf_Scn *scn; + int rc; + + rc = EX_OK; + /* If entire file is choosen, treat it as a binary file */ + if (entire_file) + return handle_binary(name, fd); + + (void) lseek(fd, (off_t)0, SEEK_SET); + elf = elf_begin(fd, ELF_C_READ, NULL); + if (elf_kind(elf) != ELF_K_ELF) { + (void) elf_end(elf); + return handle_binary(name, fd); + } + + if (gelf_getehdr(elf, &elfhdr) == NULL) { + (void) elf_end(elf); + warnx("%s: ELF file could not be processed", name); + return(EX_SOFTWARE); + } + + if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) { + (void) elf_end(elf); + return handle_binary(name, fd); + } else { + scn = NULL; + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) == NULL) + continue; + if (shdr.sh_type != SHT_NOBITS && + (shdr.sh_flags & SHF_ALLOC) != 0) { + rc = find_strings(name, shdr.sh_offset, + shdr.sh_size); + } + } + } + (void) elf_end(elf); + return(rc); +} + +/* + * Retrieves a character from input stream based on the encoding + * type requested. + */ +long +getcharacter() +{ + long rt; + int i; + char buf[4], c; + + rt = EOF; + for(i = 0; i < encoding_size; i++) { + c = getc(stdin); + if (feof(stdin)) + return(EOF); + buf[i] = c; + } + + switch(encoding) { + case ENCODING_7BIT: + case ENCODING_8BIT: + rt = buf[0]; + break; + case ENCODING_16BIT_BIG: + rt = (buf[0] << 8) | buf[1]; + break; + case ENCODING_16BIT_LITTLE: + rt = buf[0] | (buf[1] << 8); + break; + case ENCODING_32BIT_BIG: + rt = ((long) buf[0] << 24) | ((long) buf[1] << 16) | + ((long) buf[2] << 8) | buf[3]; + break; + case ENCODING_32BIT_LITTLE: + rt = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) | + ((long) buf[3] << 24); + break; + } + return(rt); +} + +/* + * Input stream stdin is read until the end of file is reached or until + * the section size is reached in case of ELF files. Contiguous + * characters of >= min_size(default 4) will be displayed. + */ +int +find_strings(const char *name, off_t offset, off_t size) +{ + off_t cur_off, start_off; + char *obuf; + long c; + int i; + + if ((obuf = (char*)calloc(1, min_len + 1)) == NULL) { + (void) fprintf(stderr, "Unable to allocate memory: %s\n", + strerror(errno)); + return(EX_SOFTWARE); + } + + (void) fseeko(stdin, offset, SEEK_SET); + cur_off = offset; + start_off = 0; + while(1) { + if ((offset + size) && (cur_off >= offset + size)) + break; + start_off = cur_off; + memset(obuf, 0, min_len+1); + for(i = 0; i < min_len; i++) { + c = getcharacter(); + if (c == EOF && feof(stdin)) + goto _exit1; + if (PRINTABLE(c)) { + obuf[i] = c; + obuf[i+1] = 0; + cur_off += encoding_size; + } else { + if (encoding == ENCODING_8BIT && + (uint8_t)c > 127) { + obuf[i] = c; + obuf[i+1] = 0; + cur_off += encoding_size; + continue; + } + cur_off += encoding_size; + break; + } + } + + if (i >= min_len && ((cur_off <= offset + size) || + !(offset + size))) { + if (show_filename) + printf ("%s: ", name); + if (show_loc) { + switch(radix) { + case RADIX_DECIMAL: + (void) printf("%7Ld ", + (uint64_t)start_off); + break; + case RADIX_HEX: + (void) printf("%7Lx ", + (uint64_t)start_off); + break; + case RADIX_OCTAL: + (void) printf("%7Lo ", + (uint64_t)start_off); + break; + } + } + printf("%s", obuf); + + while(1) { + if ((offset + size) && + (cur_off >= offset + size)) + break; + c = getcharacter(); + cur_off += encoding_size; + if (encoding == ENCODING_8BIT && + (uint8_t)c > 127) { + putchar(c); + continue; + } + if (!PRINTABLE(c) || c == EOF) + break; + putchar(c); + } + putchar('\n'); + } + } +_exit1: + free(obuf); + return(EX_OK); +} + +void +usage() +{ + (void) fprintf(stderr, + "strings [-afho] [-e s|S|l|L|b|B] [-n #] [-t o|x|d] file ...\n"); + exit(EX_USAGE); +} + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |