X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=flthdr.c;h=cf6fe4de01649aaef71ab2b377a97af4f4030704;hb=6a93642380b57bb272b96df6a350e50a4c984015;hp=fb60fb0c6c4b0cdcbbdda565dd76a28a80ff4ef9;hpb=331697f8d22fe815bec229184ea99384d245881c;p=uclinux-h8%2Felf2flt.git diff --git a/flthdr.c b/flthdr.c index fb60fb0..cf6fe4d 100644 --- a/flthdr.c +++ b/flthdr.c @@ -4,6 +4,9 @@ * * Copyright (C) 2001-2003 SnapGear Inc, davidm@snapgear.com * Copyright (C) 2001 Lineo, davidm@lineo.com + * + * This is Free Software, under the GNU Public Licence v2 or greater. + * */ /****************************************************************************/ @@ -12,75 +15,71 @@ #include #include /* exit() */ #include /* strcat(), strcpy() */ +#include +#include /* macros for conversion between host and (internet) network byte order */ +#ifndef WIN32 #include /* Consts and structs defined by the internet system */ +#define BINARY_FILE_OPTS +#else +#include +#define BINARY_FILE_OPTS "b" +#endif + +#include "compress.h" +#include /* from uClinux-x.x.x/include/linux */ #include "flat.h" /* Binary flat header description */ -/****************************************************************************/ +#if defined(__MINGW32__) +#include -char *program_name; +#define mkstemp(p) mktemp(p) + +#endif -static char cmd[1024]; -static int print = 0, compress = 0, ramload = 0, stacksize = 0, ktrace = 0; -static int short_format = 0; +#if defined TARGET_bfin +# define flat_get_relocate_addr(addr) (addr & 0x03ffffff) +#else +# define flat_get_relocate_addr(addr) (addr) +#endif /****************************************************************************/ -void -transferr(FILE *ifp, FILE *ofp, int count) -{ - int n, num; +char *program_name; + +static int print = 0, print_relocs = 0, docompress = 0, ramload = 0, + stacksize = 0, ktrace = 0; - while (count == -1 || count > 0) { - if (count == -1 || count > sizeof(cmd)) - num = sizeof(cmd); - else - num = count; - n = fread(cmd, 1, num, ifp); - if (n == 0) - break; - if (fwrite(cmd, n, 1, ofp) != 1) { - fprintf(stderr, "Write failed :-(\n"); - exit(1); - } - if (count != -1) - count -= n; - } - if (count > 0) { - fprintf(stderr, "Failed to transferr %d bytes\n", count); - exit(1); - } -} - /****************************************************************************/ void process_file(char *ifile, char *ofile) { int old_flags, old_stack, new_flags, new_stack; - FILE *ifp, *ofp; - int ofp_is_pipe = 0; + stream ifp, ofp; struct flat_hdr old_hdr, new_hdr; - char tfile[256]; - char tfile2[256]; + char *tfile, tmpbuf[256]; + int input_error, output_error; - *tfile = *tfile2 = '\0'; + *tmpbuf = '\0'; - if ((ifp = fopen(ifile, "rb")) == NULL) { + if (fopen_stream_u(&ifp, ifile, "r" BINARY_FILE_OPTS)) { fprintf(stderr, "Cannot open %s\n", ifile); return; } - if (fread(&old_hdr, sizeof(old_hdr), 1, ifp) != 1) { + if (fread_stream(&old_hdr, sizeof(old_hdr), 1, &ifp) != 1) { fprintf(stderr, "Cannot read header of %s\n", ifile); + fclose_stream(&ifp); return; } if (strncmp(old_hdr.magic, "bFLT", 4) != 0) { fprintf(stderr, "Cannot read header of %s\n", ifile); + fclose_stream(&ifp); return; } @@ -88,13 +87,13 @@ process_file(char *ifile, char *ofile) new_stack = old_stack = ntohl(old_hdr.stack_size); new_hdr = old_hdr; - if (compress == 1) { + if (docompress == 1) { new_flags |= FLAT_FLAG_GZIP; new_flags &= ~FLAT_FLAG_GZDATA; - } else if (compress == 2) { + } else if (docompress == 2) { new_flags |= FLAT_FLAG_GZDATA; new_flags &= ~FLAT_FLAG_GZIP; - } else if (compress < 0) + } else if (docompress < 0) new_flags &= ~(FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA); if (ramload > 0) @@ -112,6 +111,7 @@ process_file(char *ifile, char *ofile) if (print == 1) { time_t t; + uint32_t reloc_count, reloc_start; printf("%s\n", ifile); printf(" Magic: %4.4s\n", old_hdr.magic); @@ -123,8 +123,10 @@ process_file(char *ifile, char *ofile) printf(" Data End: 0x%x\n", ntohl(old_hdr.data_end)); printf(" BSS End: 0x%x\n", ntohl(old_hdr.bss_end)); printf(" Stack Size: 0x%x\n", ntohl(old_hdr.stack_size)); - printf(" Reloc Start: 0x%x\n", ntohl(old_hdr.reloc_start)); - printf(" Reloc Count: 0x%x\n", ntohl(old_hdr.reloc_count)); + reloc_start = ntohl(old_hdr.reloc_start); + printf(" Reloc Start: 0x%x\n", reloc_start); + reloc_count = ntohl(old_hdr.reloc_count); + printf(" Reloc Count: 0x%x\n", reloc_count); printf(" Flags: 0x%x ( ", ntohl(old_hdr.flags)); if (old_flags) { if (old_flags & FLAT_FLAG_RAM) @@ -139,6 +141,41 @@ process_file(char *ifile, char *ofile) printf("Kernel-Traced-Load "); printf(")\n"); } + + if (print_relocs) { + uint32_t *relocs = xcalloc(reloc_count, sizeof(uint32_t)); + uint32_t i; + unsigned long r; + + printf(" Relocs:\n"); + printf(" #\treloc ( address )\tdata\n"); + + if (old_flags & FLAT_FLAG_GZIP) + reopen_stream_compressed(&ifp); + if (fseek_stream(&ifp, reloc_start, SEEK_SET)) { + fprintf(stderr, "Cannot seek to relocs of %s\n", ifile); + fclose_stream(&ifp); + return; + } + if (fread_stream(relocs, sizeof(uint32_t), reloc_count, &ifp) == -1) { + fprintf(stderr, "Cannot read relocs of %s\n", ifile); + fclose_stream(&ifp); + return; + } + + for (i = 0; i < reloc_count; ++i) { + uint32_t raddr, addr; + r = ntohl(relocs[i]); + raddr = flat_get_relocate_addr(r); + printf(" %u\t0x%08lx (0x%08"PRIx32")\t", i, r, raddr); + fseek_stream(&ifp, sizeof(old_hdr) + raddr, SEEK_SET); + fread_stream(&addr, sizeof(addr), 1, &ifp); + printf("%"PRIx32"\n", addr); + } + + /* reset file position for below */ + fseek_stream(&ifp, sizeof(old_hdr), SEEK_SET); + } } else if (print > 1) { static int first = 1; unsigned int text, data, bss, stk, rel, tot; @@ -148,13 +185,13 @@ process_file(char *ifile, char *ofile) printf("-----------------------------------------------------------\n"); first = 0; } - *tfile = '\0'; - strcat(tfile, (old_flags & FLAT_FLAG_KTRACE) ? "k" : ""); - strcat(tfile, (old_flags & FLAT_FLAG_RAM) ? "r" : ""); - strcat(tfile, (old_flags & FLAT_FLAG_GOTPIC) ? "p" : ""); - strcat(tfile, (old_flags & FLAT_FLAG_GZIP) ? "z" : + *tmpbuf = '\0'; + strcat(tmpbuf, (old_flags & FLAT_FLAG_KTRACE) ? "k" : ""); + strcat(tmpbuf, (old_flags & FLAT_FLAG_RAM) ? "r" : ""); + strcat(tmpbuf, (old_flags & FLAT_FLAG_GOTPIC) ? "p" : ""); + strcat(tmpbuf, (old_flags & FLAT_FLAG_GZIP) ? "z" : ((old_flags & FLAT_FLAG_GZDATA) ? "d" : "")); - printf("-%-3.3s ", tfile); + printf("-%-3.3s ", tmpbuf); printf("%3d ", ntohl(old_hdr.rev)); printf("%6d ", text=ntohl(old_hdr.data_start)-sizeof(struct flat_hdr)); printf("%6d ", data=ntohl(old_hdr.data_end)-ntohl(old_hdr.data_start)); @@ -184,112 +221,82 @@ process_file(char *ifile, char *ofile) } /* if there is nothing else to do, leave */ - if (new_flags == old_flags && new_stack == old_stack) + if (new_flags == old_flags && new_stack == old_stack) { + fclose_stream(&ifp); return; - + } + new_hdr.flags = htonl(new_flags); new_hdr.stack_size = htonl(new_stack); - strcpy(tfile, "/tmp/flatXXXXXX"); - mkstemp(tfile); - if ((ofp = fopen(tfile, "wb")) == NULL) { + tfile = make_temp_file("flthdr"); + + if (fopen_stream_u(&ofp, tfile, "w" BINARY_FILE_OPTS)) { fprintf(stderr, "Failed to open %s for writing\n", tfile); unlink(tfile); - unlink(tfile2); exit(1); } - if (fwrite(&new_hdr, sizeof(new_hdr), 1, ofp) != 1) { + /* Copy header (always uncompressed). */ + if (fwrite_stream(&new_hdr, sizeof(new_hdr), 1, &ofp) != 1) { fprintf(stderr, "Failed to write to %s\n", tfile); unlink(tfile); - unlink(tfile2); exit(1); } - /* - * get ourselves a fully uncompressed copy of the text/data/relocs - * so that we can manipulate it more easily - */ - if (old_flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) { - FILE *tfp; - - strcpy(tfile2, "/tmp/flat2XXXXXX"); - mkstemp(tfile2); - - if (old_flags & FLAT_FLAG_GZDATA) { - tfp = fopen(tfile2, "wb"); - if (!tfp) { - fprintf(stderr, "Failed to open %s for writing\n", tfile2); - exit(1); - } - transferr(ifp, tfp, ntohl(old_hdr.data_start) - - sizeof(struct flat_hdr)); - fclose(tfp); - } - - sprintf(cmd, "gunzip >> %s", tfile2); - tfp = popen(cmd, "wb"); - if(!tfp) { - perror("popen"); - exit(1); - } - transferr(ifp, tfp, -1); - pclose(tfp); - - fclose(ifp); - ifp = fopen(tfile2, "rb"); - if (!ifp) { - fprintf(stderr, "Failed to open %s for reading\n", tfile2); - unlink(tfile); - unlink(tfile2); - exit(1); - } - } + /* Whole input file (including text) is compressed: start decompressing + now. */ + if (old_flags & FLAT_FLAG_GZIP) + reopen_stream_compressed(&ifp); + /* Likewise, output file is compressed. Start compressing now. */ if (new_flags & FLAT_FLAG_GZIP) { printf("zflat %s --> %s\n", ifile, ofile); - fclose(ofp); - sprintf(cmd, "gzip -9 -f >> %s", tfile); - ofp = popen(cmd, "wb"); - ofp_is_pipe = 1; - } else if (new_flags & FLAT_FLAG_GZDATA) { - printf("zflat-data %s --> %s\n", ifile, ofile); - transferr(ifp, ofp, ntohl(new_hdr.data_start) - - sizeof(struct flat_hdr)); - fclose(ofp); - sprintf(cmd, "gzip -9 -f >> %s", tfile); - ofp = popen(cmd, "wb"); - ofp_is_pipe = 1; + reopen_stream_compressed(&ofp); } - if (!ofp) { /* can only happen if using gzip/gunzip */ - fprintf(stderr, "Can't run cmd %s\n", cmd); - unlink(tfile); - unlink(tfile2); - exit(1); + transfer(&ifp, &ofp, + ntohl(old_hdr.data_start) - sizeof(struct flat_hdr)); + + /* Only data and relocs were compressed in input. Start decompressing + from here. */ + if (old_flags & FLAT_FLAG_GZDATA) + reopen_stream_compressed(&ifp); + + /* Only data/relocs to be compressed in output. Start compressing + from here. */ + if (new_flags & FLAT_FLAG_GZDATA) { + printf("zflat-data %s --> %s\n", ifile, ofile); + reopen_stream_compressed(&ofp); } - transferr(ifp, ofp, -1); - - if (ferror(ifp) || ferror(ofp)) { + transfer(&ifp, &ofp, -1); + + input_error = ferror_stream(&ifp); + output_error = ferror_stream(&ofp); + + if (input_error || output_error) { fprintf(stderr, "Error on file pointer%s%s\n", - ferror(ifp) ? " input" : "", ferror(ofp) ? " output" : ""); + input_error ? " input" : "", + output_error ? " output" : ""); unlink(tfile); - unlink(tfile2); exit(1); } - fclose(ifp); - if (ofp_is_pipe) - pclose(ofp); - else - fclose(ofp); + fclose_stream(&ifp); + fclose_stream(&ofp); + + /* Copy temporary file to output location. */ + fopen_stream_u(&ifp, tfile, "r" BINARY_FILE_OPTS); + fopen_stream_u(&ofp, ofile, "w" BINARY_FILE_OPTS); + + transfer(&ifp, &ofp, -1); + + fclose_stream(&ifp); + fclose_stream(&ofp); - /* cheat a little here to preserve file permissions */ - sprintf(cmd, "cp %s %s", tfile, ofile); - system(cmd); unlink(tfile); - unlink(tfile2); + free(tfile); } /****************************************************************************/ @@ -302,6 +309,7 @@ usage(char *s) fprintf(stderr, "usage: %s [options] flat-file\n", program_name); fprintf(stderr, " Allows you to change an existing flat file\n\n"); fprintf(stderr, " -p : print current settings\n"); + fprintf(stderr, " -P : print relocations\n"); fprintf(stderr, " -z : compressed flat file\n"); fprintf(stderr, " -d : compressed data-only flat file\n"); fprintf(stderr, " -Z : un-compressed flat file\n"); @@ -325,18 +333,22 @@ main(int argc, char *argv[]) program_name = argv[0]; - while ((c = getopt(argc, argv, "pdzZrRkKs:o:")) != EOF) { + while ((c = getopt(argc, argv, "pPdzZrRkKs:o:")) != EOF) { switch (c) { case 'p': print = 1; break; - case 'z': compress = 1; break; - case 'd': compress = 2; break; - case 'Z': compress = -1; break; + case 'P': print_relocs = 1; break; + case 'z': docompress = 1; break; + case 'd': docompress = 2; break; + case 'Z': docompress = -1; break; case 'r': ramload = 1; break; case 'R': ramload = -1; break; case 'k': ktrace = 1; break; case 'K': ktrace = -1; break; - case 's': stacksize = atoi(optarg); break; case 'o': ofile = optarg; break; + case 's': + if (sscanf(optarg, "%i", &stacksize) != 1) + usage("invalid stack size"); + break; default: usage("invalid option"); break; @@ -348,8 +360,8 @@ main(int argc, char *argv[]) if (ofile && argc - optind > 1) usage("-o can only be used with a single file"); - - if (!print && !compress && !ramload && !stacksize) /* no args == print */ + + if (!print && !docompress && !ramload && !stacksize) /* no args == print */ print = argc - optind; /* greater than 1 is short format */ for (c = optind; c < argc; c++) {