Initial commit (from git)

This commit is contained in:
convert-repo
2000-05-19 16:04:55 +00:00
commit 1a9128a473
130 changed files with 31392 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
# Makefile for sstrip
sstrip: sstrip.c
gcc -ggdb -Wall -W -o sstrip sstrip.c
clean:
rm -f sstrip
+40
View File
@@ -0,0 +1,40 @@
sstrip is a small utility that removes the contents at the end of an
ELF file that are not part of the program's memory image.
Most ELF executables are built with both a program header table and a
section header table. However, only the former is required in order
for the OS to load, link and execute a program. sstrip attempts to
extract the ELF header, the program header table, and its contents,
leaving everything else in the bit bucket. It can only remove parts of
the file that occur at the end, after the parts to be saved. However,
this almost always includes the section header table, and occasionally
a few random sections that are not used when running a program.
It should be noted that the GNU bfd library is (understandably)
dependent on the section header table as an index to the file's
contents. Thus, an executable file that has no section header table
cannot be used with gdb, objdump, or any other program based upon the
bfd library, at all. In fact, the program will not even recognize the
file as a valid executable. (This limitation is noted in the source
code comments for bfd, and is marked "FIXME", so this may change at
some future date. However, I would imagine that it is a pretty
low-priority item, as executables without a section header table are
rare in the extreme.) This probably also explains why strip doesn't
offer the option to do this.
Shared library files may also have their section header table removed.
Such a library will still function; however, it will no longer be
possible for a compiler to link a new program against it.
As an added bonus, sstrip also tries to removes trailing zero bytes
from the end of the file. (This normally cannot be done with an
executable that has a section header table.)
sstrip is a very simplistic program. It depends upon the common
practice of putting the parts of the file that contribute to the
memory image at the front, and the remaining material at the end. This
permits it to discard the latter material without affecting file
offsets and memory addresses in what remains. However, the ELF
standard permits files to be organized in almost any order. So
although this procedure usually works in practice, it is not meant to
be taken too seriously.
+70
View File
@@ -0,0 +1,70 @@
This distribution is a collection of programs that are generally
unrelated, except in that they all deal with the ELF file format.
The main purpose of these programs is to be illustrative and
educational -- to help fellow programmers understand the ELF file
format and something of how it works under the Linux platform. For the
most part, these programs have limited real-world utility. (Although I
myself have found these programs quite useful while writing the
others.)
Each program is independent. There is no shared code between them, and
in fact they all take slightly different approaches to handling ELF
files.
The table of contents:
sstrip/
sstrip is a small utility that removes everything from an ELF file
that is not part of the file's memory image.
elfls/
elfls is a utility that displays an ELF file's program and/or
section header tables, which serve as a kind of global roadmap to
the file's contents.
elftoc/
elftoc takes an ELF file and generates C code that defines a
structure with the same memory image, using the structures and
preprocessor symbols defined in <linux/elf.h>.
ebfc/
ebfc is a compiler for a tiny programming language. The compiler can
generate ELF executables, object files, and shared libraries.
tiny/
This directory contains a collection of very small ELF executables.
See the README in each directory for more details.
The ELF standard is necessary reading if you wish to fully understand
how these programs work. You can download a copy as a Postscript
document from ftp://tsx.mit.edu/pub/linux/packages/GCC/ELF.doc.tar.gz.
Alternately, you can obtain a flat-text transcription of this document
from http://www.muppetlabs.com/~breadbox/software/ELF.txt.
All these programs are Copyright (C) 1999 by Brian Raiter.
These programs are all free software; you can redistribute and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
These programs are distributed in the hope that they will be
interesting, but without any warranty; without even the implied
warranty of merchantability or fitness for a particular purpose.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program, in the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA.
Bug reports and general feedback should be directed to the author at
breadbox@muppetlabs.com.
Share and enjoy.
Brian Raiter
breadbox@muppetlabs.com
July, 1999
+218
View File
@@ -0,0 +1,218 @@
/* sstrip, version 1.0: Copyright (C) 1999 by Brian Raiter, under the
* GNU General Public License. No warranty. See COPYING for details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <linux/elf.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
/* The memory-allocation macro.
*/
#define alloc(p, n) (((p) = realloc(p, n)) \
|| (fputs("Out of memory.\n", stderr), \
exit(EXIT_FAILURE), 0))
static char const *thefilename; /* the current file name */
static FILE *thefile; /* the current file handle */
static Elf32_Ehdr elfhdr; /* original ELF header */
static Elf32_Phdr *phdrs = NULL; /* original program header tbl */
static unsigned long phdrsize; /* size of program header tbl */
static unsigned long newsize; /* size of the new file */
/* An error-handling function. The given error message is used only
* when errno is not set.
*/
static int err(char const *errmsg)
{
if (errno)
perror(thefilename);
else
fprintf(stderr, "%s: %s\n", thefilename, errmsg);
return FALSE;
}
/* readheaders() reads the ELF header and the program header table,
* and checks to make sure that this is in fact a file that we should
* be munging.
*/
static int readheaders(void)
{
int bigend;
errno = 0;
if (fread(&elfhdr, sizeof elfhdr, 1, thefile) != 1)
return err("not an ELF file.");
if (elfhdr.e_ident[EI_MAG0] != ELFMAG0
|| elfhdr.e_ident[EI_MAG1] != ELFMAG1
|| elfhdr.e_ident[EI_MAG2] != ELFMAG2
|| elfhdr.e_ident[EI_MAG3] != ELFMAG3)
return err("not an ELF file.");
bigend = TRUE;
*(char*)&bigend = 0;
if (elfhdr.e_ident[EI_DATA] != (bigend ? ELFDATA2MSB : ELFDATA2LSB)) {
fprintf(stderr, "%s: not %s-endian.\n",
thefilename, bigend ? "big" : "little");
return FALSE;
}
if (elfhdr.e_ehsize != sizeof(Elf32_Ehdr)) {
fprintf(stderr, "%s: unrecognized ELF header size "
"(size = %u instead of %u).\n",
thefilename, elfhdr.e_ehsize, sizeof(Elf32_Ehdr));
return FALSE;
}
if (!elfhdr.e_phoff)
return err("no program header table.");
if (elfhdr.e_phentsize != sizeof(Elf32_Phdr)) {
fprintf(stderr, "%s: unrecognized program header size "
"(size = %u instead of %u).\n",
thefilename, elfhdr.e_phentsize, sizeof(Elf32_Ehdr));
return FALSE;
}
phdrsize = elfhdr.e_phnum * elfhdr.e_phentsize;
alloc(phdrs, phdrsize);
errno = 0;
if (fread(phdrs, phdrsize, 1, thefile) != 1)
return err("invalid program header table.");
return TRUE;
}
/* getloadsize() determines the offset of the last byte of the file
* that is actually loaded into memory. Anything after this point can
* be safely discarded.
*/
static int getloadsize(void)
{
Elf32_Phdr *phdr;
unsigned long n;
int i;
newsize = elfhdr.e_phoff + phdrsize;
phdr = phdrs;
for (i = 0 ; i < elfhdr.e_phnum ; ++i) {
if (phdr->p_type == PT_NULL || phdr->p_type == PT_NOTE)
continue;
n = phdr->p_offset + phdr->p_filesz;
if (n > newsize)
newsize = n;
phdr = (Elf32_Phdr*)((char*)phdr + elfhdr.e_phentsize);
}
for (i = 0 ; i < elfhdr.e_phnum ; ++i)
if (phdr->p_filesz > 0 && phdr->p_offset >= newsize)
memset(phdr, 0, elfhdr.e_phentsize);
return TRUE;
}
/* truncatezeros() examines the bytes at the end of the file's
* size-to-be, and reduces the size to exclude trailing zero bytes.
*/
static int truncatezeros(void)
{
char contents[1024];
unsigned long n;
do {
n = sizeof contents;
if (n > newsize)
n = newsize;
if (fseek(thefile, newsize - n, SEEK_SET)
|| fread(contents, n, 1, thefile) != 1)
return err("cannot read file contents");
while (n && !contents[--n])
--newsize;
} while (newsize && !n);
return TRUE;
}
/* modifyheaders() removes references to the section header table if
* it was removed, and reduces program header table entries that
* included truncated bytes at the end of the file.
*/
static int modifyheaders(void)
{
Elf32_Phdr *phdr;
int i;
if (elfhdr.e_shoff >= newsize) {
elfhdr.e_shoff = 0;
elfhdr.e_shnum = 0;
elfhdr.e_shentsize = 0;
elfhdr.e_shstrndx = 0;
}
phdr = phdrs;
for (i = 0 ; i < elfhdr.e_phnum ; ++i) {
if (phdr->p_offset + phdr->p_filesz > newsize) {
if (phdr->p_offset >= newsize)
phdr->p_filesz = 0;
else
phdr->p_filesz = newsize - phdr->p_offset;
}
phdr = (Elf32_Phdr*)((char*)phdr + elfhdr.e_phentsize);
}
return TRUE;
}
/* savestripped() writes the new headers back to the original file
* and sets the new file size.
*/
static int savestripped(void)
{
rewind(thefile);
errno = 0;
if (fwrite(&elfhdr, sizeof elfhdr, 1, thefile) != 1
|| fwrite(phdrs, phdrsize, 1, thefile) != 1
|| ftruncate(fileno(thefile), newsize)) {
err("could not write contents");
fprintf(stderr, "WARNING: %s may be corrupted!\n", thefilename);
return FALSE;
}
return TRUE;
}
/* main() loops over the cmdline arguments, leaving all the real work
* to the other functions.
*/
int main(int argc, char *argv[])
{
char **arg;
int ret = 0;
if (argc < 2 || !strcmp(argv[1], "-h")) {
printf("sstrip, version 2.0: Copyright (C) 1999 Brian Raiter\n"
"Usage: sstrip FILE...\n");
return 0;
}
for (arg = argv + 1 ; (thefilename = *arg) != NULL ; ++arg) {
if (!(thefile = fopen(thefilename, "rb+"))) {
err("unable to open.");
++ret;
continue;
}
if (!readheaders() || !getloadsize() || !truncatezeros()
|| !modifyheaders() || !savestripped())
++ret;
fclose(thefile);
}
return ret;
}