]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/elfkickers/elfkickers-2.0a/mjn3-sstrip.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / elfkickers / elfkickers-2.0a / mjn3-sstrip.patch
1 Index: ELFkickers/sstrip/sstrip.c
2 ===================================================================
3 --- ELFkickers.orig/sstrip/sstrip.c     2001-03-24 07:18:52.000000000 -0500
4 +++ ELFkickers/sstrip/sstrip.c  2004-08-24 01:31:10.000000000 -0400
5 @@ -1,5 +1,55 @@
6 +/* http://www.muppetlabs.com/~breadbox/software/elfkickers.html */
7 +
8  /* sstrip: Copyright (C) 1999-2001 by Brian Raiter, under the GNU
9   * General Public License. No warranty. See COPYING for details.
10 + *
11 + * Aug 23, 2004 Hacked by Manuel Novoa III <mjn3@codepoet.org> to
12 + * handle targets of different endianness and/or elf class, making
13 + * it more useful in a cross-devel environment.
14 + */
15 +
16 +/* ============== original README ===================
17 + *
18 + * sstrip is a small utility that removes the contents at the end of an
19 + * ELF file that are not part of the program's memory image.
20 + * 
21 + * Most ELF executables are built with both a program header table and a
22 + * section header table. However, only the former is required in order
23 + * for the OS to load, link and execute a program. sstrip attempts to
24 + * extract the ELF header, the program header table, and its contents,
25 + * leaving everything else in the bit bucket. It can only remove parts of
26 + * the file that occur at the end, after the parts to be saved. However,
27 + * this almost always includes the section header table, and occasionally
28 + * a few random sections that are not used when running a program.
29 + * 
30 + * It should be noted that the GNU bfd library is (understandably)
31 + * dependent on the section header table as an index to the file's
32 + * contents. Thus, an executable file that has no section header table
33 + * cannot be used with gdb, objdump, or any other program based upon the
34 + * bfd library, at all. In fact, the program will not even recognize the
35 + * file as a valid executable. (This limitation is noted in the source
36 + * code comments for bfd, and is marked "FIXME", so this may change at
37 + * some future date. However, I would imagine that it is a pretty
38 + * low-priority item, as executables without a section header table are
39 + * rare in the extreme.) This probably also explains why strip doesn't
40 + * offer the option to do this.
41 + * 
42 + * Shared library files may also have their section header table removed.
43 + * Such a library will still function; however, it will no longer be
44 + * possible for a compiler to link a new program against it.
45 + * 
46 + * As an added bonus, sstrip also tries to removes trailing zero bytes
47 + * from the end of the file. (This normally cannot be done with an
48 + * executable that has a section header table.)
49 + * 
50 + * sstrip is a very simplistic program. It depends upon the common
51 + * practice of putting the parts of the file that contribute to the
52 + * memory image at the front, and the remaining material at the end. This
53 + * permits it to discard the latter material without affecting file
54 + * offsets and memory addresses in what remains. Of course, the ELF
55 + * standard permits files to be organized in almost any order, so if a
56 + * pathological linker decided to put its section headers at the top,
57 + * sstrip would be useless on such executables.
58   */
59  
60  #include       <stdio.h>
61 @@ -9,28 +59,21 @@
62  #include       <unistd.h>
63  #include       <fcntl.h>
64  #include       <elf.h>
65 -#include       <asm/elf.h>
66 +#include       <endian.h>
67 +#include       <byteswap.h>
68  
69  #ifndef TRUE
70  #define        TRUE            1
71  #define        FALSE           0
72  #endif
73  
74 -#if ELF_CLASS == ELFCLASS32
75 -#define        Elf_Ehdr        Elf32_Ehdr
76 -#define        Elf_Phdr        Elf32_Phdr
77 -#else
78 -#define        Elf_Ehdr        Elf64_Ehdr
79 -#define        Elf_Phdr        Elf64_Phdr
80 -#endif
81 -
82  /* The name of the program.
83   */
84 -static char const      *progname;
85 +static char const      *progname;
86  
87  /* The name of the current file.
88   */
89 -static char const      *filename;
90 +static char const      *filename;
91  
92  
93  /* A simple error-handling function. FALSE is always returned for the
94 @@ -38,227 +81,321 @@
95   */
96  static int err(char const *errmsg)
97  {
98 -    fprintf(stderr, "%s: %s: %s\n", progname, filename, errmsg);
99 -    return FALSE;
100 +       fprintf(stderr, "%s: %s: %s\n", progname, filename, errmsg);
101 +       return FALSE;
102  }
103  
104 -/* A macro for I/O errors: The given error message is used only when
105 - * errno is not set.
106 +/* A flag to signal the need for endian reversal.
107   */
108 -#define        ferr(msg)       (err(errno ? strerror(errno) : (msg)))
109 +static int do_reverse_endian;
110  
111 -/* readelfheader() reads the ELF header into our global variable, and
112 - * checks to make sure that this is in fact a file that we should be
113 - * munging.
114 +/* Get a value from the elf header, compensating for endianness.
115   */
116 -static int readelfheader(int fd, Elf_Ehdr *ehdr)
117 -{
118 -    errno = 0;
119 -    if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr)
120 -       return ferr("missing or incomplete ELF header.");
121 -
122 -    /* Check the ELF signature.
123 -     */
124 -    if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 &&
125 -         ehdr->e_ident[EI_MAG1] == ELFMAG1 &&
126 -         ehdr->e_ident[EI_MAG2] == ELFMAG2 &&
127 -         ehdr->e_ident[EI_MAG3] == ELFMAG3))
128 -       return err("missing ELF signature.");
129 -
130 -    /* Compare the file's class and endianness with the program's.
131 -     */
132 -    if (ehdr->e_ident[EI_DATA] != ELF_DATA)
133 -       return err("ELF file has different endianness.");
134 -    if (ehdr->e_ident[EI_CLASS] != ELF_CLASS)
135 -       return err("ELF file has different word size.");
136 -
137 -    /* Check the target architecture.
138 -     */
139 -    if (ehdr->e_machine != ELF_ARCH)
140 -       return err("ELF file created for different architecture.");
141 -
142 -    /* Verify the sizes of the ELF header and the program segment
143 -     * header table entries.
144 -     */
145 -    if (ehdr->e_ehsize != sizeof(Elf_Ehdr))
146 -       return err("unrecognized ELF header size.");
147 -    if (ehdr->e_phentsize != sizeof(Elf_Phdr))
148 -       return err("unrecognized program segment header size.");
149 -
150 -    /* Finally, check the file type.
151 -     */
152 -    if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
153 -       return err("not an executable or shared-object library.");
154 +#define EGET(X) \
155 +       (__extension__ ({ \
156 +               uint64_t __res; \
157 +               if (!do_reverse_endian) { \
158 +                       __res = (X); \
159 +               } else if (sizeof(X) == 1) { \
160 +                       __res = (X); \
161 +               } else if (sizeof(X) == 2) { \
162 +                       __res = bswap_16((X)); \
163 +               } else if (sizeof(X) == 4) { \
164 +                       __res = bswap_32((X)); \
165 +               } else if (sizeof(X) == 8) { \
166 +                       __res = bswap_64((X)); \
167 +               } else { \
168 +                       fprintf(stderr, "%s: %s: EGET failed for size %d\n", \
169 +                                       progname, filename, sizeof(X)); \
170 +                       exit(EXIT_FAILURE); \
171 +               } \
172 +               __res; \
173 +       }))
174 +
175 +/* Set a value 'Y' in the elf header to 'X', compensating for endianness.
176 + */
177 +#define ESET(Y,X) \
178 +               do if (!do_reverse_endian) { \
179 +                       Y = (X); \
180 +               } else if (sizeof(Y) == 1) { \
181 +                       Y = (X); \
182 +               } else if (sizeof(Y) == 2) { \
183 +                       Y = bswap_16((uint16_t)(X)); \
184 +               } else if (sizeof(Y) == 4) { \
185 +                       Y = bswap_32((uint32_t)(X)); \
186 +               } else if (sizeof(Y) == 8) { \
187 +                       Y = bswap_64((uint64_t)(X)); \
188 +               } else { \
189 +                       fprintf(stderr, "%s: %s: ESET failed for size %d\n", \
190 +                                       progname, filename, sizeof(Y)); \
191 +                       exit(EXIT_FAILURE); \
192 +               } while (0)
193  
194 -    return TRUE;
195 -}
196  
197 -/* readphdrtable() loads the program segment header table into memory.
198 +/* A macro for I/O errors: The given error message is used only when
199 + * errno is not set.
200   */
201 -static int readphdrtable(int fd, Elf_Ehdr const *ehdr, Elf_Phdr **phdrs)
202 -{
203 -    size_t     size;
204 -
205 -    if (!ehdr->e_phoff || !ehdr->e_phnum)
206 -       return err("ELF file has no program header table.");
207 +#define        ferr(msg)       (err(errno ? strerror(errno) : (msg)))
208  
209 -    size = ehdr->e_phnum * sizeof **phdrs;
210 -    if (!(*phdrs = malloc(size)))
211 -       return err("Out of memory!");
212  
213 -    errno = 0;
214 -    if (read(fd, *phdrs, size) != (ssize_t)size)
215 -       return ferr("missing or incomplete program segment header table.");
216  
217 -    return TRUE;
218 +#define HEADER_FUNCTIONS(CLASS) \
219 + \
220 +/* readelfheader() reads the ELF header into our global variable, and \
221 + * checks to make sure that this is in fact a file that we should be \
222 + * munging. \
223 + */ \
224 +static int readelfheader ## CLASS (int fd, Elf ## CLASS ## _Ehdr *ehdr) \
225 +{ \
226 +        if (read(fd, ((char *)ehdr)+EI_NIDENT, sizeof(*ehdr) - EI_NIDENT) \
227 +               != sizeof(*ehdr) - EI_NIDENT) \
228 +               return ferr("missing or incomplete ELF header."); \
229 + \
230 +       /* Verify the sizes of the ELF header and the program segment \
231 +        * header table entries. \
232 +        */ \
233 +       if (EGET(ehdr->e_ehsize) != sizeof(Elf ## CLASS ## _Ehdr)) \
234 +               return err("unrecognized ELF header size."); \
235 +       if (EGET(ehdr->e_phentsize) != sizeof(Elf ## CLASS ## _Phdr)) \
236 +               return err("unrecognized program segment header size."); \
237 + \
238 +       /* Finally, check the file type. \
239 +        */ \
240 +       if (EGET(ehdr->e_type) != ET_EXEC && EGET(ehdr->e_type) != ET_DYN) \
241 +               return err("not an executable or shared-object library."); \
242 + \
243 +       return TRUE; \
244 +} \
245 + \
246 +/* readphdrtable() loads the program segment header table into memory. \
247 + */ \
248 +static int readphdrtable ## CLASS (int fd, Elf ## CLASS ## _Ehdr const *ehdr, \
249 +                                                                  Elf ## CLASS ## _Phdr **phdrs) \
250 +{ \
251 +       size_t  size; \
252 + \
253 +       if (!EGET(ehdr->e_phoff) || !EGET(ehdr->e_phnum) \
254 +)              return err("ELF file has no program header table."); \
255 + \
256 +       size = EGET(ehdr->e_phnum) * sizeof **phdrs; \
257 +       if (!(*phdrs = malloc(size))) \
258 +               return err("Out of memory!"); \
259 + \
260 +       errno = 0; \
261 +       if (read(fd, *phdrs, size) != (ssize_t)size) \
262 +               return ferr("missing or incomplete program segment header table."); \
263 + \
264 +       return TRUE; \
265 +} \
266 + \
267 +/* getmemorysize() determines the offset of the last byte of the file \
268 + * that is referenced by an entry in the program segment header table. \
269 + * (Anything in the file after that point is not used when the program \
270 + * is executing, and thus can be safely discarded.) \
271 + */ \
272 +static int getmemorysize ## CLASS (Elf ## CLASS ## _Ehdr const *ehdr, \
273 +                                                                  Elf ## CLASS ## _Phdr const *phdrs, \
274 +                                                unsigned long *newsize) \
275 +{ \
276 +       Elf ## CLASS ## _Phdr const   *phdr; \
277 +       unsigned long   size, n; \
278 +       int                     i; \
279 + \
280 +       /* Start by setting the size to include the ELF header and the \
281 +        * complete program segment header table. \
282 +        */ \
283 +       size = EGET(ehdr->e_phoff) + EGET(ehdr->e_phnum) * sizeof *phdrs; \
284 +       if (size < sizeof *ehdr) \
285 +               size = sizeof *ehdr; \
286 + \
287 +       /* Then keep extending the size to include whatever data the \
288 +        * program segment header table references. \
289 +        */ \
290 +       for (i = 0, phdr = phdrs ; i < EGET(ehdr->e_phnum) ; ++i, ++phdr) { \
291 +               if (EGET(phdr->p_type) != PT_NULL) { \
292 +                       n = EGET(phdr->p_offset) + EGET(phdr->p_filesz); \
293 +                       if (n > size) \
294 +                               size = n; \
295 +               } \
296 +       } \
297 + \
298 +       *newsize = size; \
299 +       return TRUE; \
300 +} \
301 + \
302 +/* modifyheaders() removes references to the section header table if \
303 + * it was stripped, and reduces program header table entries that \
304 + * included truncated bytes at the end of the file. \
305 + */ \
306 +static int modifyheaders ## CLASS (Elf ## CLASS ## _Ehdr *ehdr, \
307 +                                                                  Elf ## CLASS ## _Phdr *phdrs, \
308 +                                                                  unsigned long newsize) \
309 +{ \
310 +       Elf ## CLASS ## _Phdr *phdr; \
311 +       int             i; \
312 + \
313 +       /* If the section header table is gone, then remove all references \
314 +        * to it in the ELF header. \
315 +        */ \
316 +       if (EGET(ehdr->e_shoff) >= newsize) { \
317 +               ESET(ehdr->e_shoff,0); \
318 +               ESET(ehdr->e_shnum,0); \
319 +               ESET(ehdr->e_shentsize,0); \
320 +               ESET(ehdr->e_shstrndx,0); \
321 +       } \
322 + \
323 +       /* The program adjusts the file size of any segment that was \
324 +        * truncated. The case of a segment being completely stripped out \
325 +        * is handled separately. \
326 +        */ \
327 +       for (i = 0, phdr = phdrs ; i < EGET(ehdr->e_phnum) ; ++i, ++phdr) { \
328 +               if (EGET(phdr->p_offset) >= newsize) { \
329 +                       ESET(phdr->p_offset,newsize); \
330 +                       ESET(phdr->p_filesz,0); \
331 +               } else if (EGET(phdr->p_offset) + EGET(phdr->p_filesz) > newsize) { \
332 +                       newsize -= EGET(phdr->p_offset); \
333 +                       ESET(phdr->p_filesz, newsize); \
334 +               } \
335 +       } \
336 + \
337 +       return TRUE; \
338 +} \
339 + \
340 +/* commitchanges() writes the new headers back to the original file \
341 + * and sets the file to its new size. \
342 + */ \
343 +static int commitchanges ## CLASS (int fd, Elf ## CLASS ## _Ehdr const *ehdr, \
344 +                                                                  Elf ## CLASS ## _Phdr *phdrs, \
345 +                                                                  unsigned long newsize) \
346 +{ \
347 +       size_t  n; \
348 + \
349 +       /* Save the changes to the ELF header, if any. \
350 +        */ \
351 +       if (lseek(fd, 0, SEEK_SET)) \
352 +               return ferr("could not rewind file"); \
353 +       errno = 0; \
354 +       if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) \
355 +               return err("could not modify file"); \
356 + \
357 +       /* Save the changes to the program segment header table, if any. \
358 +        */ \
359 +       if (lseek(fd, EGET(ehdr->e_phoff), SEEK_SET) == (off_t)-1) { \
360 +               err("could not seek in file."); \
361 +               goto warning; \
362 +       } \
363 +       n = EGET(ehdr->e_phnum) * sizeof *phdrs; \
364 +       if (write(fd, phdrs, n) != (ssize_t)n) { \
365 +               err("could not write to file"); \
366 +               goto warning; \
367 +       } \
368 + \
369 +       /* Eleventh-hour sanity check: don't truncate before the end of \
370 +        * the program segment header table. \
371 +        */ \
372 +       if (newsize < EGET(ehdr->e_phoff) + n) \
373 +               newsize = EGET(ehdr->e_phoff) + n; \
374 + \
375 +       /* Chop off the end of the file. \
376 +        */ \
377 +       if (ftruncate(fd, newsize)) { \
378 +               err("could not resize file"); \
379 +               goto warning; \
380 +       } \
381 + \
382 +       return TRUE; \
383 + \
384 + warning: \
385 +       return err("ELF file may have been corrupted!"); \
386  }
387  
388 -/* getmemorysize() determines the offset of the last byte of the file
389 - * that is referenced by an entry in the program segment header table.
390 - * (Anything in the file after that point is not used when the program
391 - * is executing, and thus can be safely discarded.)
392 - */
393 -static int getmemorysize(Elf_Ehdr const *ehdr, Elf_Phdr const *phdrs,
394 -                        unsigned long *newsize)
395 -{
396 -    Elf32_Phdr const   *phdr;
397 -    unsigned long      size, n;
398 -    int                        i;
399 -
400 -    /* Start by setting the size to include the ELF header and the
401 -     * complete program segment header table.
402 -     */
403 -    size = ehdr->e_phoff + ehdr->e_phnum * sizeof *phdrs;
404 -    if (size < sizeof *ehdr)
405 -       size = sizeof *ehdr;
406 -
407 -    /* Then keep extending the size to include whatever data the
408 -     * program segment header table references.
409 -     */
410 -    for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) {
411 -       if (phdr->p_type != PT_NULL) {
412 -           n = phdr->p_offset + phdr->p_filesz;
413 -           if (n > size)
414 -               size = n;
415 -       }
416 -    }
417 -
418 -    *newsize = size;
419 -    return TRUE;
420 -}
421  
422 -/* truncatezeros() examines the bytes at the end of the file's
423 - * size-to-be, and reduces the size to exclude any trailing zero
424 - * bytes.
425 +/* First elements of Elf32_Ehdr and Elf64_Ehdr are common.
426   */
427 -static int truncatezeros(int fd, unsigned long *newsize)
428 +static int readelfheaderident(int fd, Elf32_Ehdr *ehdr)
429  {
430 -    unsigned char      contents[1024];
431 -    unsigned long      size, n;
432 +       errno = 0;
433 +       if (read(fd, ehdr, EI_NIDENT) != EI_NIDENT)
434 +               return ferr("missing or incomplete ELF header.");
435 +
436 +       /* Check the ELF signature.
437 +        */
438 +       if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 &&
439 +                 ehdr->e_ident[EI_MAG1] == ELFMAG1 &&
440 +                 ehdr->e_ident[EI_MAG2] == ELFMAG2 &&
441 +                 ehdr->e_ident[EI_MAG3] == ELFMAG3))
442 +       {
443 +               err("missing ELF signature.");
444 +               return -1;
445 +       }
446  
447 -    size = *newsize;
448 -    do {
449 -       n = sizeof contents;
450 -       if (n > size)
451 -           n = size;
452 -       if (lseek(fd, size - n, SEEK_SET) == (off_t)-1)
453 -           return ferr("cannot seek in file.");
454 -       if (read(fd, contents, n) != (ssize_t)n)
455 -           return ferr("cannot read file contents");
456 -       while (n && !contents[--n])
457 -           --size;
458 -    } while (size && !n);
459 -
460 -    /* Sanity check.
461 -     */
462 -    if (!size)
463 -       return err("ELF file is completely blank!");
464 +       /* Compare the file's class and endianness with the program's.
465 +        */
466 +#if __BYTE_ORDER == __LITTLE_ENDIAN
467 +       if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
468 +               do_reverse_endian = 0;
469 +       } else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
470 +/*             fprintf(stderr, "ELF file has different endianness.\n"); */
471 +               do_reverse_endian = 1;
472 +       }
473 +#elif __BYTE_ORDER == __BIG_ENDIAN
474 +       if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
475 +/*             fprintf(stderr, "ELF file has different endianness.\n"); */
476 +               do_reverse_endian = 1;
477 +       } else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
478 +               do_reverse_endian = 0;
479 +       }
480 +#else
481 +#error unkown endianness
482 +#endif
483 +       else {
484 +               err("Unsupported endianness");
485 +               return -1;
486 +       }
487  
488 -    *newsize = size;
489 -    return TRUE;
490 +       /* Check the target architecture.
491 +        */
492 +/*      if (EGET(ehdr->e_machine) != ELF_ARCH) { */
493 +/*             /\* return err("ELF file created for different architecture."); *\/ */
494 +/*             fprintf(stderr, "ELF file created for different architecture.\n"); */
495 +/*     } */
496 +       return ehdr->e_ident[EI_CLASS];
497  }
498  
499 -/* modifyheaders() removes references to the section header table if
500 - * it was stripped, and reduces program header table entries that
501 - * included truncated bytes at the end of the file.
502 - */
503 -static int modifyheaders(Elf_Ehdr *ehdr, Elf_Phdr *phdrs,
504 -                        unsigned long newsize)
505 -{
506 -    Elf32_Phdr *phdr;
507 -    int                i;
508  
509 -    /* If the section header table is gone, then remove all references
510 -     * to it in the ELF header.
511 -     */
512 -    if (ehdr->e_shoff >= newsize) {
513 -       ehdr->e_shoff = 0;
514 -       ehdr->e_shnum = 0;
515 -       ehdr->e_shentsize = 0;
516 -       ehdr->e_shstrndx = 0;
517 -    }
518 -
519 -    /* The program adjusts the file size of any segment that was
520 -     * truncated. The case of a segment being completely stripped out
521 -     * is handled separately.
522 -     */
523 -    for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) {
524 -       if (phdr->p_offset >= newsize) {
525 -           phdr->p_offset = newsize;
526 -           phdr->p_filesz = 0;
527 -       } else if (phdr->p_offset + phdr->p_filesz > newsize) {
528 -           phdr->p_filesz = newsize - phdr->p_offset;
529 -       }
530 -    }
531 +HEADER_FUNCTIONS(32)
532  
533 -    return TRUE;
534 -}
535 +HEADER_FUNCTIONS(64)
536  
537 -/* commitchanges() writes the new headers back to the original file
538 - * and sets the file to its new size.
539 +/* truncatezeros() examines the bytes at the end of the file's
540 + * size-to-be, and reduces the size to exclude any trailing zero
541 + * bytes.
542   */
543 -static int commitchanges(int fd, Elf_Ehdr const *ehdr, Elf_Phdr *phdrs,
544 -                        unsigned long newsize)
545 +static int truncatezeros(int fd, unsigned long *newsize)
546  {
547 -    size_t     n;
548 -
549 -    /* Save the changes to the ELF header, if any.
550 -     */
551 -    if (lseek(fd, 0, SEEK_SET))
552 -       return ferr("could not rewind file");
553 -    errno = 0;
554 -    if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr)
555 -       return err("could not modify file");
556 -
557 -    /* Save the changes to the program segment header table, if any.
558 -     */
559 -    if (lseek(fd, ehdr->e_phoff, SEEK_SET) == (off_t)-1) {
560 -       err("could not seek in file.");
561 -       goto warning;
562 -    }
563 -    n = ehdr->e_phnum * sizeof *phdrs;
564 -    if (write(fd, phdrs, n) != (ssize_t)n) {
565 -       err("could not write to file");
566 -       goto warning;
567 -    }
568 -
569 -    /* Eleventh-hour sanity check: don't truncate before the end of
570 -     * the program segment header table.
571 -     */
572 -    if (newsize < ehdr->e_phoff + n)
573 -       newsize = ehdr->e_phoff + n;
574 -
575 -    /* Chop off the end of the file.
576 -     */
577 -    if (ftruncate(fd, newsize)) {
578 -       err("could not resize file");
579 -       goto warning;
580 -    }
581 +       unsigned char   contents[1024];
582 +       unsigned long   size, n;
583  
584 -    return TRUE;
585 +       size = *newsize;
586 +       do {
587 +               n = sizeof contents;
588 +               if (n > size)
589 +                       n = size;
590 +               if (lseek(fd, size - n, SEEK_SET) == (off_t)-1)
591 +                       return ferr("cannot seek in file.");
592 +               if (read(fd, contents, n) != (ssize_t)n)
593 +                       return ferr("cannot read file contents");
594 +               while (n && !contents[--n])
595 +                       --size;
596 +       } while (size && !n);
597 +
598 +       /* Sanity check.
599 +        */
600 +       if (!size)
601 +               return err("ELF file is completely blank!");
602  
603 -  warning:
604 -    return err("ELF file may have been corrupted!");
605 +       *newsize = size;
606 +       return TRUE;
607  }
608  
609  /* main() loops over the cmdline arguments, leaving all the real work
610 @@ -266,44 +403,66 @@
611   */
612  int main(int argc, char *argv[])
613  {
614 -    int                        fd;
615 -    Elf_Ehdr           ehdr;
616 -    Elf_Phdr          *phdrs;
617 -    unsigned long      newsize;
618 -    char             **arg;
619 -    int                        failures = 0;
620 -
621 -    if (argc < 2 || argv[1][0] == '-') {
622 -       printf("Usage: sstrip FILE...\n"
623 -              "sstrip discards all nonessential bytes from an executable.\n\n"
624 -              "Version 2.0 Copyright (C) 2000,2001 Brian Raiter.\n"
625 -              "This program is free software, licensed under the GNU\n"
626 -              "General Public License. There is absolutely no warranty.\n");
627 -       return EXIT_SUCCESS;
628 -    }
629 -
630 -    progname = argv[0];
631 -
632 -    for (arg = argv + 1 ; *arg != NULL ; ++arg) {
633 -       filename = *arg;
634 -
635 -       fd = open(*arg, O_RDWR);
636 -       if (fd < 0) {
637 -           ferr("can't open");
638 -           ++failures;
639 -           continue;
640 +       int                             fd;
641 +       union {
642 +               Elf32_Ehdr      ehdr32;
643 +               Elf64_Ehdr      ehdr64;
644 +       } e;
645 +       union {
646 +               Elf32_Phdr      *phdrs32;
647 +               Elf64_Phdr      *phdrs64;
648 +       } p;
649 +       unsigned long   newsize;
650 +       char                    **arg;
651 +       int                             failures = 0;
652 +
653 +       if (argc < 2 || argv[1][0] == '-') {
654 +               printf("Usage: sstrip FILE...\n"
655 +                          "sstrip discards all nonessential bytes from an executable.\n\n"
656 +                          "Version 2.0-X Copyright (C) 2000,2001 Brian Raiter.\n"
657 +                          "Cross-devel hacks Copyright (C) 2004 Manuel Novoa III.\n"
658 +                          "This program is free software, licensed under the GNU\n"
659 +                          "General Public License. There is absolutely no warranty.\n");
660 +               return EXIT_SUCCESS;
661         }
662  
663 -       if (!(readelfheader(fd, &ehdr)                  &&
664 -             readphdrtable(fd, &ehdr, &phdrs)          &&
665 -             getmemorysize(&ehdr, phdrs, &newsize)     &&
666 -             truncatezeros(fd, &newsize)               &&
667 -             modifyheaders(&ehdr, phdrs, newsize)      &&
668 -             commitchanges(fd, &ehdr, phdrs, newsize)))
669 -           ++failures;
670 +       progname = argv[0];
671  
672 -       close(fd);
673 -    }
674 +       for (arg = argv + 1 ; *arg != NULL ; ++arg) {
675 +               filename = *arg;
676 +
677 +               fd = open(*arg, O_RDWR);
678 +               if (fd < 0) {
679 +                       ferr("can't open");
680 +                       ++failures;
681 +                       continue;
682 +               }
683 +
684 +               switch (readelfheaderident(fd, &e.ehdr32)) {
685 +                       case ELFCLASS32:
686 +                               if (!(readelfheader32(fd, &e.ehdr32)                                    &&
687 +                                         readphdrtable32(fd, &e.ehdr32, &p.phdrs32)            &&
688 +                                         getmemorysize32(&e.ehdr32, p.phdrs32, &newsize)       &&
689 +                                         truncatezeros(fd, &newsize)                                           &&
690 +                                         modifyheaders32(&e.ehdr32, p.phdrs32, newsize)        &&
691 +                                         commitchanges32(fd, &e.ehdr32, p.phdrs32, newsize)))
692 +                                       ++failures;
693 +                               break;
694 +                       case ELFCLASS64:
695 +                               if (!(readelfheader64(fd, &e.ehdr64)                                    &&
696 +                                         readphdrtable64(fd, &e.ehdr64, &p.phdrs64)            &&
697 +                                         getmemorysize64(&e.ehdr64, p.phdrs64, &newsize)       &&
698 +                                         truncatezeros(fd, &newsize)                                           &&
699 +                                         modifyheaders64(&e.ehdr64, p.phdrs64, newsize)        &&
700 +                                         commitchanges64(fd, &e.ehdr64, p.phdrs64, newsize)))
701 +                                       ++failures;
702 +                               break;
703 +                       default:
704 +                               ++failures;
705 +                               break;
706 +               }
707 +               close(fd);
708 +       }
709  
710 -    return failures ? EXIT_FAILURE : EXIT_SUCCESS;
711 +       return failures ? EXIT_FAILURE : EXIT_SUCCESS;
712  }