OSDN Git Service

Unify the duplicated windows and other system fallback logic in stubs.h
[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 <inttypes.h>
19 #include <assert.h>
20
21 #include "compress.h"
22 #include <libiberty.h>
23
24 #include "stubs.h"
25 const char *elf2flt_progname;
26
27 /* from uClinux-x.x.x/include/linux */
28 #include "flat.h"     /* Binary flat header description                      */
29
30 #if defined(__MINGW32__)
31 #include <getopt.h>
32
33 #define mkstemp(p) mktemp(p)
34
35 #endif
36
37 #if defined TARGET_bfin
38 # define flat_get_relocate_addr(addr) (addr & 0x03ffffff)
39 #else
40 # define flat_get_relocate_addr(addr) (addr)
41 #endif
42
43 /****************************************************************************/
44
45 static int print = 0, print_relocs = 0, docompress = 0, ramload = 0,
46            stacksize = 0, ktrace = 0, l1stack = 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                 fclose_stream(&ifp);
69                 return;
70         }
71
72         if (strncmp(old_hdr.magic, "bFLT", 4) != 0) {
73                 fprintf(stderr, "Cannot read header of %s\n", ifile);
74                 fclose_stream(&ifp);
75                 return;
76         }
77
78         new_flags = old_flags = ntohl(old_hdr.flags);
79         new_stack = old_stack = ntohl(old_hdr.stack_size);
80         new_hdr = old_hdr;
81
82         if (docompress == 1) {
83                 new_flags |= FLAT_FLAG_GZIP;
84                 new_flags &= ~FLAT_FLAG_GZDATA;
85         } else if (docompress == 2) {
86                 new_flags |= FLAT_FLAG_GZDATA;
87                 new_flags &= ~FLAT_FLAG_GZIP;
88         } else if (docompress < 0)
89                 new_flags &= ~(FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA);
90         
91         if (ramload > 0)
92                 new_flags |= FLAT_FLAG_RAM;
93         else if (ramload < 0)
94                 new_flags &= ~FLAT_FLAG_RAM;
95         
96         if (ktrace > 0)
97                 new_flags |= FLAT_FLAG_KTRACE;
98         else if (ktrace < 0)
99                 new_flags &= ~FLAT_FLAG_KTRACE;
100         
101         if (l1stack > 0)
102                 new_flags |= FLAT_FLAG_L1STK;
103         else if (l1stack < 0)
104                 new_flags &= ~FLAT_FLAG_L1STK;
105
106         if (stacksize)
107                 new_stack = stacksize;
108
109         if (print == 1) {
110                 time_t t;
111                 uint32_t reloc_count, reloc_start;
112
113                 printf("%s\n", ifile);
114                 printf("    Magic:        %4.4s\n", old_hdr.magic);
115                 printf("    Rev:          %d\n",    ntohl(old_hdr.rev));
116                 t = (time_t) htonl(old_hdr.build_date);
117                 printf("    Build Date:   %s",      t?ctime(&t):"not specified\n");
118                 printf("    Entry:        0x%x\n",  ntohl(old_hdr.entry));
119                 printf("    Data Start:   0x%x\n",  ntohl(old_hdr.data_start));
120                 printf("    Data End:     0x%x\n",  ntohl(old_hdr.data_end));
121                 printf("    BSS End:      0x%x\n",  ntohl(old_hdr.bss_end));
122                 printf("    Stack Size:   0x%x\n",  ntohl(old_hdr.stack_size));
123                 reloc_start = ntohl(old_hdr.reloc_start);
124                 printf("    Reloc Start:  0x%x\n",  reloc_start);
125                 reloc_count = ntohl(old_hdr.reloc_count);
126                 printf("    Reloc Count:  0x%x\n",  reloc_count);
127                 printf("    Flags:        0x%x ( ",  ntohl(old_hdr.flags));
128                 if (old_flags) {
129                         if (old_flags & FLAT_FLAG_RAM)
130                                 printf("Load-to-Ram ");
131                         if (old_flags & FLAT_FLAG_GOTPIC)
132                                 printf("Has-PIC-GOT ");
133                         if (old_flags & FLAT_FLAG_GZIP)
134                                 printf("Gzip-Compressed ");
135                         if (old_flags & FLAT_FLAG_GZDATA)
136                                 printf("Gzip-Data-Compressed ");
137                         if (old_flags & FLAT_FLAG_KTRACE)
138                                 printf("Kernel-Traced-Load ");
139                         if (old_flags & FLAT_FLAG_L1STK)
140                                 printf("L1-Scratch-Stack ");
141                         printf(")\n");
142                 }
143
144                 if (print_relocs) {
145                         uint32_t *relocs = xcalloc(reloc_count, sizeof(uint32_t));
146                         uint32_t i;
147                         unsigned long r;
148
149                         printf("    Relocs:\n");
150                         printf("    #\treloc      (  address )\tdata\n");
151
152                         if (old_flags & FLAT_FLAG_GZIP)
153                                 reopen_stream_compressed(&ifp);
154                         if (fseek_stream(&ifp, reloc_start, SEEK_SET)) {
155                                 fprintf(stderr, "Cannot seek to relocs of %s\n", ifile);
156                                 fclose_stream(&ifp);
157                                 return;
158                         }
159                         if (fread_stream(relocs, sizeof(uint32_t), reloc_count, &ifp) == -1) {
160                                 fprintf(stderr, "Cannot read relocs of %s\n", ifile);
161                                 fclose_stream(&ifp);
162                                 return;
163                         }
164
165                         for (i = 0; i < reloc_count; ++i) {
166                                 uint32_t raddr, addr;
167                                 r = ntohl(relocs[i]);
168                                 raddr = flat_get_relocate_addr(r);
169                                 printf("    %u\t0x%08lx (0x%08"PRIx32")\t", i, r, raddr);
170                                 fseek_stream(&ifp, sizeof(old_hdr) + raddr, SEEK_SET);
171                                 fread_stream(&addr, sizeof(addr), 1, &ifp);
172                                 printf("%"PRIx32"\n", addr);
173                         }
174
175                         /* reset file position for below */
176                         fseek_stream(&ifp, sizeof(old_hdr), SEEK_SET);
177                 }
178         } else if (print > 1) {
179                 static int first = 1;
180                 unsigned int text, data, bss, stk, rel, tot;
181
182                 if (first) {
183                         printf("Flag Rev   Text   Data    BSS  Stack Relocs    RAM Filename\n");
184                         printf("-----------------------------------------------------------\n");
185                         first = 0;
186                 }
187                 *tmpbuf = '\0';
188                 strcat(tmpbuf, (old_flags & FLAT_FLAG_KTRACE) ? "k" : "");
189                 strcat(tmpbuf, (old_flags & FLAT_FLAG_RAM) ? "r" : "");
190                 strcat(tmpbuf, (old_flags & FLAT_FLAG_GOTPIC) ? "p" : "");
191                 strcat(tmpbuf, (old_flags & FLAT_FLAG_GZIP) ? "z" :
192                                         ((old_flags & FLAT_FLAG_GZDATA) ? "d" : ""));
193                 printf("-%-3.3s ", tmpbuf);
194                 printf("%3d ", ntohl(old_hdr.rev));
195                 printf("%6d ", text=ntohl(old_hdr.data_start)-sizeof(struct flat_hdr));
196                 printf("%6d ", data=ntohl(old_hdr.data_end)-ntohl(old_hdr.data_start));
197                 printf("%6d ", bss=ntohl(old_hdr.bss_end)-ntohl(old_hdr.data_end));
198                 printf("%6d ", stk=ntohl(old_hdr.stack_size));
199                 printf("%6d ", rel=ntohl(old_hdr.reloc_count) * 4);
200                 /*
201                  * work out how much RAM is needed per invocation, this
202                  * calculation is dependent on the binfmt_flat implementation
203                  */
204                 tot = data; /* always need data */
205
206                 if (old_flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP))
207                         tot += text + sizeof(struct flat_hdr);
208                 
209                 if (bss + stk > rel) /* which is bigger ? */
210                         tot += bss + stk;
211                 else
212                         tot += rel;
213
214                 printf("%6d ", tot);
215                 /*
216                  * the total depends on whether the relocs are smaller/bigger than
217                  * the BSS
218                  */
219                 printf("%s\n", ifile);
220         }
221
222         /* if there is nothing else to do, leave */
223         if (new_flags == old_flags && new_stack == old_stack) {
224                 fclose_stream(&ifp);
225                 return;
226         }
227
228         new_hdr.flags = htonl(new_flags);
229         new_hdr.stack_size = htonl(new_stack);
230
231         tfile = make_temp_file("flthdr");
232
233         if (fopen_stream_u(&ofp, tfile, "w" BINARY_FILE_OPTS)) {
234                 unlink(tfile);
235                 fatal("Failed to open %s for writing\n", tfile);
236         }
237
238         /* Copy header (always uncompressed).  */
239         if (fwrite_stream(&new_hdr, sizeof(new_hdr), 1, &ofp) != 1) {
240                 unlink(tfile);
241                 fatal("Failed to write to  %s\n", tfile);
242         }
243
244         /* Whole input file (including text) is compressed: start decompressing
245            now.  */
246         if (old_flags & FLAT_FLAG_GZIP)
247                 reopen_stream_compressed(&ifp);
248
249         /* Likewise, output file is compressed. Start compressing now.  */
250         if (new_flags & FLAT_FLAG_GZIP) {
251                 printf("zflat %s --> %s\n", ifile, ofile);
252                 reopen_stream_compressed(&ofp);
253         }
254
255         transfer(&ifp, &ofp,
256                   ntohl(old_hdr.data_start) - sizeof(struct flat_hdr));
257
258         /* Only data and relocs were compressed in input.  Start decompressing
259            from here.  */
260         if (old_flags & FLAT_FLAG_GZDATA)
261                 reopen_stream_compressed(&ifp);
262
263         /* Only data/relocs to be compressed in output.  Start compressing
264            from here.  */
265         if (new_flags & FLAT_FLAG_GZDATA) {
266                 printf("zflat-data %s --> %s\n", ifile, ofile);
267                 reopen_stream_compressed(&ofp);
268         }
269
270         transfer(&ifp, &ofp, -1);
271
272         input_error = ferror_stream(&ifp);
273         output_error = ferror_stream(&ofp);
274
275         if (input_error || output_error) {
276                 unlink(tfile);
277                 fatal("Error on file pointer%s%s\n",
278                                 input_error ? " input" : "",
279                                 output_error ? " output" : "");
280         }
281
282         fclose_stream(&ifp);
283         fclose_stream(&ofp);
284
285         /* Copy temporary file to output location.  */
286         fopen_stream_u(&ifp, tfile, "r" BINARY_FILE_OPTS);
287         fopen_stream_u(&ofp, ofile, "w" BINARY_FILE_OPTS);
288
289         transfer(&ifp, &ofp, -1);
290
291         fclose_stream(&ifp);
292         fclose_stream(&ofp);
293
294         unlink(tfile);
295         free(tfile);
296 }
297
298 /****************************************************************************/
299
300 void
301 usage(char *s)
302 {
303         if (s)
304                 fprintf(stderr, "%s\n", s);
305         fprintf(stderr, "usage: %s [options] flat-file\n", elf2flt_progname);
306         fprintf(stderr, "       Allows you to change an existing flat file\n\n");
307         fprintf(stderr, "       -p      : print current settings\n");
308         fprintf(stderr, "       -P      : print relocations\n");
309         fprintf(stderr, "       -z      : compressed flat file\n");
310         fprintf(stderr, "       -d      : compressed data-only flat file\n");
311         fprintf(stderr, "       -Z      : un-compressed flat file\n");
312         fprintf(stderr, "       -r      : ram load\n");
313         fprintf(stderr, "       -R      : do not RAM load\n");
314         fprintf(stderr, "       -k      : kernel traced load (for debug)\n");
315         fprintf(stderr, "       -K      : normal non-kernel traced load\n");
316         fprintf(stderr, "       -u      : place stack in L1 scratchpad memory\n");
317         fprintf(stderr, "       -U      : place stack in normal SDRAM memory\n");
318         fprintf(stderr, "       -s size : stack size\n");
319         fprintf(stderr, "       -o file : output-file\n"
320                         "                 (default is to modify input file)\n");
321         exit(1);
322 }
323
324 /****************************************************************************/
325
326 int
327 main(int argc, char *argv[])
328 {
329         int c;
330         char *ofile = NULL, *ifile;
331
332         elf2flt_progname = argv[0];
333
334         while ((c = getopt(argc, argv, "pPdzZrRuUkKs:o:")) != EOF) {
335                 switch (c) {
336                 case 'p': print = 1;                break;
337                 case 'P': print_relocs = 1;         break;
338                 case 'z': docompress = 1;           break;
339                 case 'd': docompress = 2;           break;
340                 case 'Z': docompress = -1;          break;
341                 case 'r': ramload = 1;              break;
342                 case 'R': ramload = -1;             break;
343                 case 'k': ktrace = 1;               break;
344                 case 'K': ktrace = -1;              break;
345                 case 'u': l1stack = 1;              break;
346                 case 'U': l1stack = -1;             break;
347                 case 'o': ofile = optarg;           break;
348                 case 's':
349                         if (sscanf(optarg, "%i", &stacksize) != 1)
350                                 usage("invalid stack size");
351                         break;
352                 default:
353                         usage("invalid option");
354                         break;
355                 }
356         }
357
358         if (optind >= argc)
359                 usage("No input files provided");
360
361         if (ofile && argc - optind > 1)
362                 usage("-o can only be used with a single file");
363
364         if (!print && !docompress && !ramload && !stacksize) /* no args == print */
365                 print = argc - optind; /* greater than 1 is short format */
366         
367         for (c = optind; c < argc; c++) {
368                 ifile = argv[c];
369                 if (!ofile)
370                         ofile = ifile;
371                 process_file(ifile, ofile);
372                 ofile = NULL;
373         }
374         
375         exit(0);
376 }
377
378 /****************************************************************************/