OSDN Git Service

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