| /* |
| * elfextract.c - Extract the loadable program segment from an elf file. |
| * |
| * Copyright 1996 Paul Mackerras. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it 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. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * 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; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| */ |
| |
| #include <stdio.h> |
| #include <linux/elf.h> |
| |
| FILE *fi, *fo; |
| char *ni, *no; |
| char buf[65536]; |
| |
| void |
| rd(void *buf, int len) |
| { |
| int nr; |
| |
| nr = fread(buf, 1, len, fi); |
| if (nr == len) |
| return; |
| if (ferror(fi)) |
| fprintf(stderr, "%s: read error\n", ni); |
| else |
| fprintf(stderr, "%s: short file\n", ni); |
| exit(1); |
| } |
| |
| int |
| main(int ac, char **av) |
| { |
| unsigned nb, len, i; |
| Elf32_Ehdr eh; |
| Elf32_Phdr ph; |
| unsigned long phoffset = 0; |
| unsigned long phsize = 0; |
| unsigned long prevaddr = 0; |
| |
| if (ac > 3 || (ac > 1 && av[1][0] == '-')) { |
| fprintf(stderr, "Usage: %s [elf-file [image-file]]\n", av[0]); |
| exit(0); |
| } |
| |
| fi = stdin; |
| ni = "(stdin)"; |
| fo = stdout; |
| no = "(stdout)"; |
| |
| if (ac > 1) { |
| ni = av[1]; |
| fi = fopen(ni, "rb"); |
| if (fi == NULL) { |
| perror(ni); |
| exit(1); |
| } |
| } |
| |
| rd(&eh, sizeof(eh)); |
| if (eh.e_ident[EI_MAG0] != ELFMAG0 |
| || eh.e_ident[EI_MAG1] != ELFMAG1 |
| || eh.e_ident[EI_MAG2] != ELFMAG2 |
| || eh.e_ident[EI_MAG3] != ELFMAG3) { |
| fprintf(stderr, "%s: not an ELF file\n", ni); |
| exit(1); |
| } |
| |
| fseek(fi, eh.e_phoff, 0); |
| phsize = 0; |
| for (i = 0; i < eh.e_phnum; ++i) { |
| rd(&ph, sizeof(ph)); |
| if (ph.p_type != PT_LOAD) |
| continue; |
| if (phsize == 0 || prevaddr == 0) { |
| phoffset = ph.p_offset; |
| phsize = ph.p_filesz; |
| } else |
| phsize = ph.p_offset + ph.p_filesz - phoffset; |
| prevaddr = ph.p_vaddr; |
| } |
| if (phsize == 0) { |
| fprintf(stderr, "%s: doesn't have a loadable segment\n", ni); |
| exit(1); |
| } |
| |
| if (ac > 2) { |
| no = av[2]; |
| fo = fopen(no, "wb"); |
| if (fo == NULL) { |
| perror(no); |
| exit(1); |
| } |
| } |
| |
| fseek(fi, phoffset, 0); |
| for (len = phsize; len != 0; len -= nb) { |
| nb = len; |
| if (nb > sizeof(buf)) |
| nb = sizeof(buf); |
| rd(buf, nb); |
| if (fwrite(buf, 1, nb, fo) != nb) { |
| fprintf(stderr, "%s: write error\n", no); |
| exit(1); |
| } |
| } |
| |
| fclose(fo); |
| fclose(fi); |
| exit(0); |
| } |