32769fff62fa734f2ef0fc7fe10242b6a242c058
1 /* http://www.muppetlabs.com/~breadbox/software/elfkickers.html */
3 /* sstrip: Copyright (C) 1999-2001 by Brian Raiter, under the GNU
4 * General Public License. No warranty. See COPYING for details.
8 #define _MIPS_SZLONG 32
17 #include <linux/bitops.h>
19 typedef signed char s8
;
20 typedef unsigned char u8
;
22 typedef signed short s16
;
23 typedef unsigned short u16
;
25 typedef signed int s32
;
26 typedef unsigned int u32
;
28 typedef signed long long s64
;
29 typedef unsigned long long u64
;
38 #if ELF_CLASS == ELFCLASS32
39 #define Elf_Ehdr Elf32_Ehdr
40 #define Elf_Phdr Elf32_Phdr
42 #define Elf_Ehdr Elf64_Ehdr
43 #define Elf_Phdr Elf64_Phdr
46 /* The name of the program.
48 static char const *progname
;
50 /* The name of the current file.
52 static char const *filename
;
55 /* A simple error-handling function. FALSE is always returned for the
56 * convenience of the caller.
58 static int err(char const *errmsg
)
60 fprintf(stderr
, "%s: %s: %s\n", progname
, filename
, errmsg
);
64 /* A macro for I/O errors: The given error message is used only when
67 #define ferr(msg) (err(errno ? strerror(errno) : (msg)))
69 /* readelfheader() reads the ELF header into our global variable, and
70 * checks to make sure that this is in fact a file that we should be
73 static int readelfheader(int fd
, Elf_Ehdr
*ehdr
)
76 if (read(fd
, ehdr
, sizeof *ehdr
) != sizeof *ehdr
)
77 return ferr("missing or incomplete ELF header.");
79 /* Check the ELF signature.
81 if (!(ehdr
->e_ident
[EI_MAG0
] == ELFMAG0
&&
82 ehdr
->e_ident
[EI_MAG1
] == ELFMAG1
&&
83 ehdr
->e_ident
[EI_MAG2
] == ELFMAG2
&&
84 ehdr
->e_ident
[EI_MAG3
] == ELFMAG3
))
85 return err("missing ELF signature.");
87 /* Compare the file's class and endianness with the program's.
89 if (ehdr
->e_ident
[EI_DATA
] != ELF_DATA
)
90 return err("ELF file has different endianness.");
91 if (ehdr
->e_ident
[EI_CLASS
] != ELF_CLASS
)
92 return err("ELF file has different word size.");
94 /* Check the target architecture.
96 if (ehdr
->e_machine
!= ELF_ARCH
)
97 return err("ELF file created for different architecture.");
98 /* Verify the sizes of the ELF header and the program segment
99 * header table entries.
101 if (ehdr
->e_ehsize
!= sizeof(Elf_Ehdr
))
102 return err("unrecognized ELF header size.");
103 if (ehdr
->e_phentsize
!= sizeof(Elf_Phdr
))
104 return err("unrecognized program segment header size.");
106 /* Finally, check the file type.
108 if (ehdr
->e_type
!= ET_EXEC
&& ehdr
->e_type
!= ET_DYN
)
109 return err("not an executable or shared-object library.");
114 /* readphdrtable() loads the program segment header table into memory.
116 static int readphdrtable(int fd
, Elf_Ehdr
const *ehdr
, Elf_Phdr
**phdrs
)
120 if (!ehdr
->e_phoff
|| !ehdr
->e_phnum
)
121 return err("ELF file has no program header table.");
123 size
= ehdr
->e_phnum
* sizeof **phdrs
;
124 if (!(*phdrs
= malloc(size
)))
125 return err("Out of memory!");
128 if (read(fd
, *phdrs
, size
) != (ssize_t
)size
)
129 return ferr("missing or incomplete program segment header table.");
134 /* getmemorysize() determines the offset of the last byte of the file
135 * that is referenced by an entry in the program segment header table.
136 * (Anything in the file after that point is not used when the program
137 * is executing, and thus can be safely discarded.)
139 static int getmemorysize(Elf_Ehdr
const *ehdr
, Elf_Phdr
const *phdrs
,
140 unsigned long *newsize
)
142 Elf32_Phdr
const *phdr
;
143 unsigned long size
, n
;
146 /* Start by setting the size to include the ELF header and the
147 * complete program segment header table.
149 size
= ehdr
->e_phoff
+ ehdr
->e_phnum
* sizeof *phdrs
;
150 if (size
< sizeof *ehdr
)
153 /* Then keep extending the size to include whatever data the
154 * program segment header table references.
156 for (i
= 0, phdr
= phdrs
; i
< ehdr
->e_phnum
; ++i
, ++phdr
) {
157 if (phdr
->p_type
!= PT_NULL
) {
158 n
= phdr
->p_offset
+ phdr
->p_filesz
;
168 /* truncatezeros() examines the bytes at the end of the file's
169 * size-to-be, and reduces the size to exclude any trailing zero
172 static int truncatezeros(int fd
, unsigned long *newsize
)
174 unsigned char contents
[1024];
175 unsigned long size
, n
;
182 if (lseek(fd
, size
- n
, SEEK_SET
) == (off_t
)-1)
183 return ferr("cannot seek in file.");
184 if (read(fd
, contents
, n
) != (ssize_t
)n
)
185 return ferr("cannot read file contents");
186 while (n
&& !contents
[--n
])
188 } while (size
&& !n
);
193 return err("ELF file is completely blank!");
199 /* modifyheaders() removes references to the section header table if
200 * it was stripped, and reduces program header table entries that
201 * included truncated bytes at the end of the file.
203 static int modifyheaders(Elf_Ehdr
*ehdr
, Elf_Phdr
*phdrs
,
204 unsigned long newsize
)
209 /* If the section header table is gone, then remove all references
210 * to it in the ELF header.
212 if (ehdr
->e_shoff
>= newsize
) {
215 ehdr
->e_shentsize
= 0;
216 ehdr
->e_shstrndx
= 0;
219 /* The program adjusts the file size of any segment that was
220 * truncated. The case of a segment being completely stripped out
221 * is handled separately.
223 for (i
= 0, phdr
= phdrs
; i
< ehdr
->e_phnum
; ++i
, ++phdr
) {
224 if (phdr
->p_offset
>= newsize
) {
225 phdr
->p_offset
= newsize
;
227 } else if (phdr
->p_offset
+ phdr
->p_filesz
> newsize
) {
228 phdr
->p_filesz
= newsize
- phdr
->p_offset
;
235 /* commitchanges() writes the new headers back to the original file
236 * and sets the file to its new size.
238 static int commitchanges(int fd
, Elf_Ehdr
const *ehdr
, Elf_Phdr
*phdrs
,
239 unsigned long newsize
)
243 /* Save the changes to the ELF header, if any.
245 if (lseek(fd
, 0, SEEK_SET
))
246 return ferr("could not rewind file");
248 if (write(fd
, ehdr
, sizeof *ehdr
) != sizeof *ehdr
)
249 return err("could not modify file");
251 /* Save the changes to the program segment header table, if any.
253 if (lseek(fd
, ehdr
->e_phoff
, SEEK_SET
) == (off_t
)-1) {
254 err("could not seek in file.");
257 n
= ehdr
->e_phnum
* sizeof *phdrs
;
258 if (write(fd
, phdrs
, n
) != (ssize_t
)n
) {
259 err("could not write to file");
263 /* Eleventh-hour sanity check: don't truncate before the end of
264 * the program segment header table.
266 if (newsize
< ehdr
->e_phoff
+ n
)
267 newsize
= ehdr
->e_phoff
+ n
;
269 /* Chop off the end of the file.
271 if (ftruncate(fd
, newsize
)) {
272 err("could not resize file");
279 return err("ELF file may have been corrupted!");
282 /* main() loops over the cmdline arguments, leaving all the real work
283 * to the other functions.
285 int main(int argc
, char *argv
[])
290 unsigned long newsize
;
294 if (argc
< 2 || argv
[1][0] == '-') {
295 printf("Usage: sstrip FILE...\n"
296 "sstrip discards all nonessential bytes from an executable.\n\n"
297 "Version 2.0 Copyright (C) 2000,2001 Brian Raiter.\n"
298 "This program is free software, licensed under the GNU\n"
299 "General Public License. There is absolutely no warranty.\n");
305 for (arg
= argv
+ 1 ; *arg
!= NULL
; ++arg
) {
308 fd
= open(*arg
, O_RDWR
);
315 if (!(readelfheader(fd
, &ehdr
) &&
316 readphdrtable(fd
, &ehdr
, &phdrs
) &&
317 getmemorysize(&ehdr
, phdrs
, &newsize
) &&
318 truncatezeros(fd
, &newsize
) &&
319 modifyheaders(&ehdr
, phdrs
, newsize
) &&
320 commitchanges(fd
, &ehdr
, phdrs
, newsize
)))
326 return failures
? EXIT_FAILURE
: EXIT_SUCCESS
;
This page took 0.056105 seconds and 3 git commands to generate.