Commit yaboot 1.3.6
[yaboot.git] / util / elfextract.c
1 /*
2  *  elfextract.c - Extract the loadable program segment from an elf file.
3  *
4  *  Copyright 1996 Paul Mackerras.
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  */
20
21 #include <stdio.h>
22 #include <linux/elf.h>
23
24 FILE *fi, *fo;
25 char *ni, *no;
26 char buf[65536];
27
28 void
29 rd(void *buf, int len)
30 {
31     int nr;
32
33     nr = fread(buf, 1, len, fi);
34     if (nr == len)
35         return;
36     if (ferror(fi))
37         fprintf(stderr, "%s: read error\n", ni);
38     else
39         fprintf(stderr, "%s: short file\n", ni);
40     exit(1);
41 }
42
43 int
44 main(int ac, char **av)
45 {
46     unsigned nb, len, i;
47     Elf32_Ehdr eh;
48     Elf32_Phdr ph;
49     unsigned long phoffset, phsize, prevaddr;
50
51     if (ac > 3 || (ac > 1 && av[1][0] == '-')) {
52         fprintf(stderr, "Usage: %s [elf-file [image-file]]\n", av[0]);
53         exit(0);
54     }
55
56     fi = stdin;
57     ni = "(stdin)";
58     fo = stdout;
59     no = "(stdout)";
60
61     if (ac > 1) {
62         ni = av[1];
63         fi = fopen(ni, "rb");
64         if (fi == NULL) {
65             perror(ni);
66             exit(1);
67         }
68     }
69
70     rd(&eh, sizeof(eh));
71     if (eh.e_ident[EI_MAG0] != ELFMAG0
72         || eh.e_ident[EI_MAG1] != ELFMAG1
73         || eh.e_ident[EI_MAG2] != ELFMAG2
74         || eh.e_ident[EI_MAG3] != ELFMAG3) {
75         fprintf(stderr, "%s: not an ELF file\n", ni);
76         exit(1);
77     }
78
79     fseek(fi, eh.e_phoff, 0);
80     phsize = 0;
81     for (i = 0; i < eh.e_phnum; ++i) {
82         rd(&ph, sizeof(ph));
83         if (ph.p_type != PT_LOAD)
84             continue;
85         if (phsize == 0 || prevaddr == 0) {
86             phoffset = ph.p_offset;
87             phsize = ph.p_filesz;
88         } else
89             phsize = ph.p_offset + ph.p_filesz - phoffset;
90         prevaddr = ph.p_vaddr;
91     }
92     if (phsize == 0) {
93         fprintf(stderr, "%s: doesn't have a loadable segment\n", ni);
94         exit(1);
95     }
96
97     if (ac > 2) {
98         no = av[2];
99         fo = fopen(no, "wb");
100         if (fo == NULL) {
101             perror(no);
102             exit(1);
103         }
104     }
105
106     fseek(fi, phoffset, 0);
107     for (len = phsize; len != 0; len -= nb) {
108         nb = len;
109         if (nb > sizeof(buf))
110             nb = sizeof(buf);
111         rd(buf, nb);
112         if (fwrite(buf, 1, nb, fo) != nb) {
113             fprintf(stderr, "%s: write error\n", no);
114             exit(1);
115         }
116     }
117
118     fclose(fo);
119     fclose(fi);
120     exit(0);
121 }