summaryrefslogtreecommitdiffstats
path: root/src/sstrip.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sstrip.c')
-rw-r--r--src/sstrip.c538
1 files changed, 0 insertions, 538 deletions
diff --git a/src/sstrip.c b/src/sstrip.c
deleted file mode 100644
index a296561..0000000
--- a/src/sstrip.c
+++ /dev/null
@@ -1,538 +0,0 @@
-/* sstrip, version 2.0: Copyright (C) 1999-2001 by Brian Raiter, under the
- * GNU General Public License. No warranty. See LICENSE for details.
- */
-
-/* Modified for portability and 64bit/32bit elf executables, Rainer Wichmann */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#if !defined(__ia64) && !defined(__ia64__) && !defined(__itanium__) && \
- !defined(__alpha) && !defined(__alpha__) && \
- (defined(HAVE_ELF_H) || defined(HAVE_LINUX_ELF_H)) && \
- (defined(__linux__) || defined(__FreeBSD__)) && \
- (defined(__i386__) || defined(__i386) || defined(i386))
-
-/* || defined(__sun) || defined(__sun__) || defined(sun) */
-
-
-#if defined(HAVE_ELF_H)
-#include <elf.h>
-#else
-#include <linux/elf.h>
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-
-#ifndef ELFCLASS32
-#define ELFCLASS32 1 /* 32-bit objects */
-#endif
-#ifndef ELFCLASS64
-#define ELFCLASS64 2 /* 64-bit objects */
-#endif
-
-
-
-/* The name of the program.
- */
-static char const *progname;
-
-/* The name of the current file.
- */
-static char const *filename;
-
-
-/* A simple error-handling function. FALSE is always returned for the
- * convenience of the caller.
- */
-static int err(char const *errmsg)
-{
- fprintf(stderr, "%s: %s: %s\n", progname, filename, errmsg);
- return FALSE;
-}
-
-/* A macro for I/O errors: The given error message is used only when
- * errno is not set.
- */
-#define ferr(msg) (err(errno ? strerror(errno) : (msg)))
-
-/* readelfheader() reads the ELF header into our global variable, and
- * checks to make sure that this is in fact a file that we should be
- * munging.
- */
-static int readelfheader_32(int fd, Elf32_Ehdr *ehdr)
-{
- errno = 0;
- if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr)
- return ferr("missing or incomplete ELF header.");
-
- /* Check the ELF signature.
- */
- if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 &&
- ehdr->e_ident[EI_MAG1] == ELFMAG1 &&
- ehdr->e_ident[EI_MAG2] == ELFMAG2 &&
- ehdr->e_ident[EI_MAG3] == ELFMAG3))
- return err("missing ELF signature.");
-
- /* Compare the file's class and endianness with the program's.
- */
-#ifdef ELF_DATA
- if (ehdr->e_ident[EI_DATA] != ELF_DATA)
- return err("ELF file has different endianness.");
-#endif
-
- if (ehdr->e_ident[EI_CLASS] != ELFCLASS32)
- return FALSE;
-
- /* Check the target architecture.
- */
-#ifdef ELF_ARCH
- if (ehdr->e_machine != ELF_ARCH)
- return err("ELF file created for different architecture.");
-#endif
-
- /* Verify the sizes of the ELF header and the program segment
- * header table entries.
- */
- if (ehdr->e_ehsize != sizeof(Elf32_Ehdr))
- return err("unrecognized ELF header size.");
- if (ehdr->e_phentsize != sizeof(Elf32_Phdr))
- return err("unrecognized program segment header size.");
-
- /* Finally, check the file type.
- */
- if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
- return err("not an executable or shared-object library.");
-
- return TRUE;
-}
-
-static int readelfheader_64(int fd, Elf64_Ehdr *ehdr)
-{
- errno = 0;
-
- if (lseek(fd, 0, SEEK_SET))
- return ferr("could not rewind file");
-
- if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr)
- return ferr("missing or incomplete ELF header.");
-
- /* Check the ELF signature.
- */
- if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 &&
- ehdr->e_ident[EI_MAG1] == ELFMAG1 &&
- ehdr->e_ident[EI_MAG2] == ELFMAG2 &&
- ehdr->e_ident[EI_MAG3] == ELFMAG3))
- return err("missing ELF signature.");
-
- /* Compare the file's class and endianness with the program's.
- */
-#ifdef ELF_DATA
- if (ehdr->e_ident[EI_DATA] != ELF_DATA)
- return err("ELF file has different endianness.");
-#endif
-
- if (ehdr->e_ident[EI_CLASS] != ELFCLASS64)
- return err("ELF file has different word size.");
-
- /* Check the target architecture.
- */
-#ifdef ELF_ARCH
- if (ehdr->e_machine != ELF_ARCH)
- return err("ELF file created for different architecture.");
-#endif
-
- /* Verify the sizes of the ELF header and the program segment
- * header table entries.
- */
- if (ehdr->e_ehsize != sizeof(Elf64_Ehdr))
- return err("unrecognized ELF header size.");
- if (ehdr->e_phentsize != sizeof(Elf64_Phdr))
- return err("unrecognized program segment header size.");
-
- /* Finally, check the file type.
- */
- if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
- return err("not an executable or shared-object library.");
-
- return TRUE;
-}
-
-/* readphdrtable() loads the program segment header table into memory.
- */
-static int readphdrtable_32(int fd, Elf32_Ehdr const *ehdr, Elf32_Phdr **phdrs)
-{
- size_t size;
-
- if (!ehdr->e_phoff || !ehdr->e_phnum)
- return err("ELF file has no program header table.");
-
- size = ehdr->e_phnum * sizeof **phdrs;
- if (!(*phdrs = calloc(1,size)))
- return err("Out of memory!");
-
- errno = 0;
- if (read(fd, *phdrs, size) != (ssize_t)size)
- return ferr("missing or incomplete program segment header table.");
-
- return TRUE;
-}
-
-static int readphdrtable_64(int fd, Elf64_Ehdr const *ehdr, Elf64_Phdr **phdrs)
-{
- size_t size;
-
- if (!ehdr->e_phoff || !ehdr->e_phnum)
- return err("ELF file has no program header table.");
-
- size = ehdr->e_phnum * sizeof **phdrs;
- if (!(*phdrs = calloc(1,size)))
- return err("Out of memory!");
-
- errno = 0;
- if (read(fd, *phdrs, size) != (ssize_t)size)
- return ferr("missing or incomplete program segment header table.");
-
- return TRUE;
-}
-
-/* getmemorysize() determines the offset of the last byte of the file
- * that is referenced by an entry in the program segment header table.
- * (Anything in the file after that point is not used when the program
- * is executing, and thus can be safely discarded.)
- */
-static int getmemorysize_32(Elf32_Ehdr const *ehdr, Elf32_Phdr const *phdrs,
- unsigned long *newsize)
-{
- Elf32_Phdr const *phdr;
- unsigned long size, n;
- unsigned int i;
-
- /* Start by setting the size to include the ELF header and the
- * complete program segment header table.
- */
- size = ehdr->e_phoff + ehdr->e_phnum * sizeof *phdrs;
- if (size < sizeof *ehdr)
- size = sizeof *ehdr;
-
- /* Then keep extending the size to include whatever data the
- * program segment header table references.
- */
- for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) {
- if (phdr->p_type != PT_NULL) {
- n = phdr->p_offset + phdr->p_filesz;
- if (n > size)
- size = n;
- }
- }
-
- *newsize = size;
- return TRUE;
-}
-
-static int getmemorysize_64(Elf64_Ehdr const *ehdr, Elf64_Phdr const *phdrs,
- unsigned long *newsize)
-{
- Elf64_Phdr const *phdr;
- unsigned long size, n;
- unsigned int i;
-
- /* Start by setting the size to include the ELF header and the
- * complete program segment header table.
- */
- size = ehdr->e_phoff + ehdr->e_phnum * sizeof *phdrs;
- if (size < sizeof *ehdr)
- size = sizeof *ehdr;
-
- /* Then keep extending the size to include whatever data the
- * program segment header table references.
- */
- for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) {
- if (phdr->p_type != PT_NULL) {
- n = phdr->p_offset + phdr->p_filesz;
- if (n > size)
- size = n;
- }
- }
-
- *newsize = size;
- return TRUE;
-}
-
-/* truncatezeros() examines the bytes at the end of the file's
- * size-to-be, and reduces the size to exclude any trailing zero
- * bytes.
- */
-static int truncatezeros(int fd, unsigned long *newsize)
-{
- unsigned char contents[1024];
- unsigned long size, n;
-
- size = *newsize;
- do {
- n = sizeof contents;
- if (n > size)
- n = size;
- if (lseek(fd, size - n, SEEK_SET) == (off_t)-1)
- return ferr("cannot seek in file.");
- if (read(fd, contents, n) != (ssize_t)n)
- return ferr("cannot read file contents");
- while (n && !contents[--n])
- --size;
- } while (size && !n);
-
- /* Sanity check.
- */
- if (!size)
- return err("ELF file is completely blank!");
-
- *newsize = size;
- return TRUE;
-}
-
-/* modifyheaders() removes references to the section header table if
- * it was stripped, and reduces program header table entries that
- * included truncated bytes at the end of the file.
- */
-static int modifyheaders_32(Elf32_Ehdr *ehdr, Elf32_Phdr *phdrs,
- unsigned long newsize)
-{
- Elf32_Phdr *phdr;
- unsigned int i;
-
- /* If the section header table is gone, then remove all references
- * to it in the ELF header.
- */
- if (ehdr->e_shoff >= newsize) {
- ehdr->e_shoff = 0;
- ehdr->e_shnum = 0;
- ehdr->e_shentsize = 0;
- ehdr->e_shstrndx = 0;
- }
-
- /* The program adjusts the file size of any segment that was
- * truncated. The case of a segment being completely stripped out
- * is handled separately.
- */
- for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) {
- if (phdr->p_offset >= newsize) {
- phdr->p_offset = newsize;
- phdr->p_filesz = 0;
- } else if (phdr->p_offset + phdr->p_filesz > newsize) {
- phdr->p_filesz = newsize - phdr->p_offset;
- }
- }
-
- return TRUE;
-}
-
-static int modifyheaders_64(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs,
- unsigned long newsize)
-{
- Elf64_Phdr *phdr;
- unsigned int i;
-
- /* If the section header table is gone, then remove all references
- * to it in the ELF header.
- */
- if (ehdr->e_shoff >= newsize) {
- ehdr->e_shoff = 0;
- ehdr->e_shnum = 0;
- ehdr->e_shentsize = 0;
- ehdr->e_shstrndx = 0;
- }
-
- /* The program adjusts the file size of any segment that was
- * truncated. The case of a segment being completely stripped out
- * is handled separately.
- */
- for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) {
- if (phdr->p_offset >= newsize) {
- phdr->p_offset = newsize;
- phdr->p_filesz = 0;
- } else if (phdr->p_offset + phdr->p_filesz > newsize) {
- phdr->p_filesz = newsize - phdr->p_offset;
- }
- }
-
- return TRUE;
-}
-
-/* commitchanges() writes the new headers back to the original file
- * and sets the file to its new size.
- */
-static int commitchanges_32(int fd, Elf32_Ehdr const *ehdr, Elf32_Phdr *phdrs,
- unsigned long newsize)
-{
- size_t n;
-
- /* Save the changes to the ELF header, if any.
- */
- if (lseek(fd, 0, SEEK_SET))
- return ferr("could not rewind file");
- errno = 0;
- if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr)
- return err("could not modify file");
-
- /* Save the changes to the program segment header table, if any.
- */
- if (lseek(fd, ehdr->e_phoff, SEEK_SET) == (off_t)-1) {
- err("could not seek in file.");
- goto warning;
- }
- n = ehdr->e_phnum * sizeof *phdrs;
- if (write(fd, phdrs, n) != (ssize_t)n) {
- err("could not write to file");
- goto warning;
- }
-
- /* Eleventh-hour sanity check: don't truncate before the end of
- * the program segment header table.
- */
- if (newsize < ehdr->e_phoff + n)
- newsize = ehdr->e_phoff + n;
-
- /* Chop off the end of the file.
- */
- if (ftruncate(fd, newsize)) {
- err("could not resize file");
- goto warning;
- }
-
- return TRUE;
-
- warning:
- return err("ELF file may have been corrupted!");
-}
-
-static int commitchanges_64(int fd, Elf64_Ehdr const *ehdr, Elf64_Phdr *phdrs,
- unsigned long newsize)
-{
- size_t n;
-
- /* Save the changes to the ELF header, if any.
- */
- if (lseek(fd, 0, SEEK_SET))
- return ferr("could not rewind file");
- errno = 0;
- if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr)
- return err("could not modify file");
-
- /* Save the changes to the program segment header table, if any.
- */
- if (lseek(fd, ehdr->e_phoff, SEEK_SET) == (off_t)-1) {
- err("could not seek in file.");
- goto warning;
- }
- n = ehdr->e_phnum * sizeof *phdrs;
- if (write(fd, phdrs, n) != (ssize_t)n) {
- err("could not write to file");
- goto warning;
- }
-
- /* Eleventh-hour sanity check: don't truncate before the end of
- * the program segment header table.
- */
- if (newsize < ehdr->e_phoff + n)
- newsize = ehdr->e_phoff + n;
-
- /* Chop off the end of the file.
- */
- if (ftruncate(fd, newsize)) {
- err("could not resize file");
- goto warning;
- }
-
- return TRUE;
-
- warning:
- return err("ELF file may have been corrupted!");
-}
-
-/* main() loops over the cmdline arguments, leaving all the real work
- * to the other functions.
- */
-int main(int argc, char *argv[])
-{
- int fd;
- int is_32bit_elf;
- Elf32_Ehdr ehdr32;
- Elf32_Phdr *phdrs32 = NULL;
- Elf64_Ehdr ehdr64;
- Elf64_Phdr *phdrs64 = NULL;
- unsigned long newsize;
- char **arg;
- int failures = 0;
-
- if (argc < 2 || argv[1][0] == '-') {
- printf("Usage: sstrip FILE...\n"
- "sstrip discards all nonessential bytes from an executable.\n\n"
- "Version 2.0 Copyright (C) 2000,2001 Brian Raiter.\n"
- "This program is free software, licensed under the GNU\n"
- "General Public License. There is absolutely no warranty.\n");
- return EXIT_SUCCESS;
- }
-
- progname = argv[0];
-
- for (arg = argv + 1 ; *arg != NULL ; ++arg) {
- filename = *arg;
-
- fd = open(*arg, O_RDWR);
- if (fd < 0) {
- ferr("can't open");
- ++failures;
- continue;
- }
-
- if (readelfheader_32(fd, &ehdr32)) {
- is_32bit_elf = TRUE;
- }
- else if (readelfheader_64(fd, &ehdr64)) {
- is_32bit_elf = FALSE;
- }
- else {
- close(fd);
- return EXIT_FAILURE;
- }
-
- if (is_32bit_elf) {
- if (!(readphdrtable_32(fd, &ehdr32, &phdrs32) &&
- getmemorysize_32(&ehdr32, phdrs32, &newsize) &&
- truncatezeros(fd, &newsize) &&
- modifyheaders_32(&ehdr32, phdrs32, newsize) &&
- commitchanges_32(fd, &ehdr32, phdrs32, newsize)))
- ++failures;
- }
- else {
- if (!(readphdrtable_64(fd, &ehdr64, &phdrs64) &&
- getmemorysize_64(&ehdr64, phdrs64, &newsize) &&
- truncatezeros(fd, &newsize) &&
- modifyheaders_64(&ehdr64, phdrs64, newsize) &&
- commitchanges_64(fd, &ehdr64, phdrs64, newsize)))
- ++failures;
- }
-
- close(fd);
- }
-
- return failures ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
-#else
-
-int main()
-{
- return (EXIT_SUCCESS);
-}
-
-#endif