OSDN Git Service

This patch allows elf2flt/flthdr's compression options to work in a wider
[uclinux-h8/elf2flt.git] / flthdr.c
1 /****************************************************************************/
2 /*
3  *      A simple program to manipulate flat files
4  *
5  *      Copyright (C) 2001-2003 SnapGear Inc, davidm@snapgear.com
6  *      Copyright (C) 2001 Lineo, davidm@lineo.com
7  *
8  * This is Free Software, under the GNU Public Licence v2 or greater.
9  *
10  */
11 /****************************************************************************/
12
13 #include <stdio.h>    /* Userland pieces of the ANSI C standard I/O package  */
14 #include <unistd.h>   /* Userland prototypes of the Unix std system calls    */
15 #include <time.h>
16 #include <stdlib.h>   /* exit() */
17 #include <string.h>   /* strcat(), strcpy() */
18 #include <assert.h>
19
20 /* macros for conversion between host and (internet) network byte order */
21 #ifndef WIN32
22 #include <netinet/in.h> /* Consts and structs defined by the internet system */
23 #define BINARY_FILE_OPTS
24 #else
25 #include <winsock2.h>
26 #define BINARY_FILE_OPTS "b"
27 #endif
28
29 #include "compress.h"
30 #include <libiberty.h>
31
32 /* from uClinux-x.x.x/include/linux */
33 #include "flat.h"     /* Binary flat header description                      */
34
35 #if defined(__MINGW32__)
36 #include <getopt.h>
37
38 #define mkstemp(p) mktemp(p)
39
40 #endif
41
42 /****************************************************************************/
43
44 char *program_name;
45
46 static int print = 0, docompress = 0, ramload = 0, stacksize = 0, ktrace = 0;
47
48 /****************************************************************************/
49
50 void
51 process_file(char *ifile, char *ofile)
52 {
53         int old_flags, old_stack, new_flags, new_stack;
54         stream ifp, ofp;
55         struct flat_hdr old_hdr, new_hdr;
56         char *tfile, tmpbuf[256];
57         int input_error, output_error;
58
59         *tmpbuf = '\0';
60
61         if (fopen_stream_u(&ifp, ifile, "r" BINARY_FILE_OPTS)) {
62                 fprintf(stderr, "Cannot open %s\n", ifile);
63                 return;
64         }
65
66         if (fread_stream(&old_hdr, sizeof(old_hdr), 1, &ifp) != 1) {
67                 fprintf(stderr, "Cannot read header of %s\n", ifile);
68                 return;
69         }
70
71         if (strncmp(old_hdr.magic, "bFLT", 4) != 0) {
72                 fprintf(stderr, "Cannot read header of %s\n", ifile);
73                 return;
74         }
75
76         new_flags = old_flags = ntohl(old_hdr.flags);
77         new_stack = old_stack = ntohl(old_hdr.stack_size);
78         new_hdr = old_hdr;
79
80         if (docompress == 1) {
81                 new_flags |= FLAT_FLAG_GZIP;
82                 new_flags &= ~FLAT_FLAG_GZDATA;
83         } else if (docompress == 2) {
84                 new_flags |= FLAT_FLAG_GZDATA;
85                 new_flags &= ~FLAT_FLAG_GZIP;
86         } else if (docompress < 0)
87                 new_flags &= ~(FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA);
88         
89         if (ramload > 0)
90                 new_flags |= FLAT_FLAG_RAM;
91         else if (ramload < 0)
92                 new_flags &= ~FLAT_FLAG_RAM;
93         
94         if (ktrace > 0)
95                 new_flags |= FLAT_FLAG_KTRACE;
96         else if (ktrace < 0)
97                 new_flags &= ~FLAT_FLAG_KTRACE;
98         
99         if (stacksize)
100                 new_stack = stacksize;
101
102         if (print == 1) {
103                 time_t t;
104
105                 printf("%s\n", ifile);
106                 printf("    Magic:        %4.4s\n", old_hdr.magic);
107                 printf("    Rev:          %d\n",    ntohl(old_hdr.rev));
108                 t = (time_t) htonl(old_hdr.build_date);
109                 printf("    Build Date:   %s",      t?ctime(&t):"not specified\n");
110                 printf("    Entry:        0x%x\n",  ntohl(old_hdr.entry));
111                 printf("    Data Start:   0x%x\n",  ntohl(old_hdr.data_start));
112                 printf("    Data End:     0x%x\n",  ntohl(old_hdr.data_end));
113                 printf("    BSS End:      0x%x\n",  ntohl(old_hdr.bss_end));
114                 printf("    Stack Size:   0x%x\n",  ntohl(old_hdr.stack_size));
115                 printf("    Reloc Start:  0x%x\n",  ntohl(old_hdr.reloc_start));
116                 printf("    Reloc Count:  0x%x\n",  ntohl(old_hdr.reloc_count));
117                 printf("    Flags:        0x%x ( ",  ntohl(old_hdr.flags));
118                 if (old_flags) {
119                         if (old_flags & FLAT_FLAG_RAM)
120                                 printf("Load-to-Ram ");
121                         if (old_flags & FLAT_FLAG_GOTPIC)
122                                 printf("Has-PIC-GOT ");
123                         if (old_flags & FLAT_FLAG_GZIP)
124                                 printf("Gzip-Compressed ");
125                         if (old_flags & FLAT_FLAG_GZDATA)
126                                 printf("Gzip-Data-Compressed ");
127                         if (old_flags & FLAT_FLAG_KTRACE)
128                                 printf("Kernel-Traced-Load ");
129                         printf(")\n");
130                 }
131         } else if (print > 1) {
132                 static int first = 1;
133                 unsigned int text, data, bss, stk, rel, tot;
134
135                 if (first) {
136                         printf("Flag Rev   Text   Data    BSS  Stack Relocs    RAM Filename\n");
137                         printf("-----------------------------------------------------------\n");
138                         first = 0;
139                 }
140                 *tmpbuf = '\0';
141                 strcat(tmpbuf, (old_flags & FLAT_FLAG_KTRACE) ? "k" : "");
142                 strcat(tmpbuf, (old_flags & FLAT_FLAG_RAM) ? "r" : "");
143                 strcat(tmpbuf, (old_flags & FLAT_FLAG_GOTPIC) ? "p" : "");
144                 strcat(tmpbuf, (old_flags & FLAT_FLAG_GZIP) ? "z" :
145                                         ((old_flags & FLAT_FLAG_GZDATA) ? "d" : ""));
146                 printf("-%-3.3s ", tmpbuf);
147                 printf("%3d ", ntohl(old_hdr.rev));
148                 printf("%6d ", text=ntohl(old_hdr.data_start)-sizeof(struct flat_hdr));
149                 printf("%6d ", data=ntohl(old_hdr.data_end)-ntohl(old_hdr.data_start));
150                 printf("%6d ", bss=ntohl(old_hdr.bss_end)-ntohl(old_hdr.data_end));
151                 printf("%6d ", stk=ntohl(old_hdr.stack_size));
152                 printf("%6d ", rel=ntohl(old_hdr.reloc_count) * 4);
153                 /*
154                  * work out how much RAM is needed per invocation, this
155                  * calculation is dependent on the binfmt_flat implementation
156                  */
157                 tot = data; /* always need data */
158
159                 if (old_flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP))
160                         tot += text + sizeof(struct flat_hdr);
161                 
162                 if (bss + stk > rel) /* which is bigger ? */
163                         tot += bss + stk;
164                 else
165                         tot += rel;
166
167                 printf("%6d ", tot);
168                 /*
169                  * the total depends on whether the relocs are smaller/bigger than
170                  * the BSS
171                  */
172                 printf("%s\n", ifile);
173         }
174
175         /* if there is nothing else to do, leave */
176         if (new_flags == old_flags && new_stack == old_stack)
177                 return;
178         
179         new_hdr.flags = htonl(new_flags);
180         new_hdr.stack_size = htonl(new_stack);
181
182         tfile = make_temp_file("flthdr");
183
184         if (fopen_stream_u(&ofp, tfile, "w" BINARY_FILE_OPTS)) {
185                 fprintf(stderr, "Failed to open %s for writing\n", tfile);
186                 unlink(tfile);
187                 exit(1);
188         }
189
190         /* Copy header (always uncompressed).  */
191         if (fwrite_stream(&new_hdr, sizeof(new_hdr), 1, &ofp) != 1) {
192                 fprintf(stderr, "Failed to write to  %s\n", tfile);
193                 unlink(tfile);
194                 exit(1);
195         }
196
197         /* Whole input file (including text) is compressed: start decompressing
198            now.  */
199         if (old_flags & FLAT_FLAG_GZIP)
200                 reopen_stream_compressed(&ifp);
201
202         /* Likewise, output file is compressed. Start compressing now.  */
203         if (new_flags & FLAT_FLAG_GZIP) {
204                 printf("zflat %s --> %s\n", ifile, ofile);
205                 reopen_stream_compressed(&ofp);
206         }
207
208         transfer(&ifp, &ofp,
209                   ntohl(old_hdr.data_start) - sizeof(struct flat_hdr));
210
211         /* Only data and relocs were compressed in input.  Start decompressing
212            from here.  */
213         if (old_flags & FLAT_FLAG_GZDATA)
214                 reopen_stream_compressed(&ifp);
215
216         /* Only data/relocs to be compressed in output.  Start compressing
217            from here.  */
218         if (new_flags & FLAT_FLAG_GZDATA) {
219                 printf("zflat-data %s --> %s\n", ifile, ofile);
220                 reopen_stream_compressed(&ofp);
221         }
222
223         transfer(&ifp, &ofp, -1);
224
225         input_error = ferror_stream(&ifp);
226         output_error = ferror_stream(&ofp);
227
228         if (input_error || output_error) {
229                 fprintf(stderr, "Error on file pointer%s%s\n",
230                                 input_error ? " input" : "",
231                                 output_error ? " output" : "");
232                 unlink(tfile);
233                 exit(1);
234         }
235
236         fclose_stream(&ifp);
237         fclose_stream(&ofp);
238
239         /* Copy temporary file to output location.  */
240         fopen_stream_u(&ifp, tfile, "r" BINARY_FILE_OPTS);
241         fopen_stream_u(&ofp, ofile, "w" BINARY_FILE_OPTS);
242
243         transfer(&ifp, &ofp, -1);
244
245         fclose_stream(&ifp);
246         fclose_stream(&ofp);
247
248         unlink(tfile);
249         free(tfile);
250 }
251
252 /****************************************************************************/
253
254 void
255 usage(char *s)
256 {
257         if (s)
258                 fprintf(stderr, "%s\n", s);
259         fprintf(stderr, "usage: %s [options] flat-file\n", program_name);
260         fprintf(stderr, "       Allows you to change an existing flat file\n\n");
261         fprintf(stderr, "       -p      : print current settings\n");
262         fprintf(stderr, "       -z      : compressed flat file\n");
263         fprintf(stderr, "       -d      : compressed data-only flat file\n");
264         fprintf(stderr, "       -Z      : un-compressed flat file\n");
265         fprintf(stderr, "       -r      : ram load\n");
266         fprintf(stderr, "       -R      : do not RAM load\n");
267         fprintf(stderr, "       -k      : kernel traced load (for debug)\n");
268         fprintf(stderr, "       -K      : normal non-kernel traced load\n");
269         fprintf(stderr, "       -s size : stack size\n");
270         fprintf(stderr, "       -o file : output-file\n"
271                         "                 (default is to modify input file)\n");
272         exit(1);
273 }
274
275 /****************************************************************************/
276
277 int
278 main(int argc, char *argv[])
279 {
280         int c;
281         char *ofile = NULL, *ifile;
282
283         program_name = argv[0];
284
285         while ((c = getopt(argc, argv, "pdzZrRkKs:o:")) != EOF) {
286                 switch (c) {
287                 case 'p': print = 1;                break;
288                 case 'z': docompress = 1;           break;
289                 case 'd': docompress = 2;           break;
290                 case 'Z': docompress = -1;          break;
291                 case 'r': ramload = 1;              break;
292                 case 'R': ramload = -1;             break;
293                 case 'k': ktrace = 1;               break;
294                 case 'K': ktrace = -1;              break;
295                 case 'o': ofile = optarg;           break;
296                 case 's':
297                         if (sscanf(optarg, "%i", &stacksize) != 1)
298                                 usage("invalid stack size");
299                         break;
300                 default:
301                         usage("invalid option");
302                         break;
303                 }
304         }
305
306         if (optind >= argc)
307                 usage("No input files provided");
308
309         if (ofile && argc - optind > 1)
310                 usage("-o can only be used with a single file");
311
312         if (!print && !docompress && !ramload && !stacksize) /* no args == print */
313                 print = argc - optind; /* greater than 1 is short format */
314         
315         for (c = optind; c < argc; c++) {
316                 ifile = argv[c];
317                 if (!ofile)
318                         ofile = ifile;
319                 process_file(ifile, ofile);
320                 ofile = NULL;
321         }
322         
323         exit(0);
324 }
325
326 /****************************************************************************/