/* Tool to make gzipped second stage binary Copyright (C) 1996,1998 Jakub Jelinek This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include FILE *f, *e; unsigned char buffer[2048]; unsigned char buffer2[2048]; unsigned short diffs[4][2048]; int ndiffs[4]; unsigned int lastv[4]; unsigned int curoff; unsigned int prevlen; unsigned int prevoff; #define MAX_CHANGE 65535 void save(FILE *out, int len, int type) { int i, j, k; int curlen = len; while (len > 0) { i = 2048; if (len < i) i = len; if (fread (buffer, 1, i, f) != i) { fprintf(stderr, "read %d from arg3 type %d failed\n", i, type); exit(1); } if (fread (buffer2, 1, i, e) != i) { fprintf(stderr, "read %d from arg4 type %d failed\n", i, type); exit(1); } for (j = 0; j < i; j++) { if (buffer[j] != buffer2[j]) { if (buffer2[j] == buffer[j] + 4) { if (curoff + j > lastv[type] + MAX_CHANGE) { if (type || !prevlen || curoff + j >= prevoff + MAX_CHANGE) goto bad1; k = lastv[type] + MAX_CHANGE; if (k < prevoff - prevlen) goto bad1; if (k >= prevoff) k = prevoff - 1; diffs[type][ndiffs[type]] = htons(k - lastv[type]); lastv[type] = k; ndiffs[type]++; } diffs[type][ndiffs[type]] = htons(curoff + j - lastv[type]); lastv[type] = curoff + j; ndiffs[type]++; } else if (buffer2[j] == buffer[j] + 16) { if (curoff + j > lastv[type+1] + MAX_CHANGE) { if (type || !prevlen || curoff + j >= prevoff + MAX_CHANGE) goto bad2; k = lastv[type+1] + MAX_CHANGE; if (k < prevoff - prevlen) goto bad2; if (k >= prevoff) k = prevoff - 1; diffs[type+1][ndiffs[type+1]] = htons(k - lastv[type+1]); lastv[type+1] = k; ndiffs[type+1]++; } diffs[type+1][ndiffs[type+1]] = htons(curoff + j - lastv[type+1]); lastv[type+1] = curoff + j; ndiffs[type+1]++; } else { fprintf(stderr, "Strange, small and large images differ in something" " different to R_SPARC_32 and R_SPARC_HI22\n"); exit(1); } } } if (fwrite (buffer, 1, i, out) != i) { fprintf(stderr, "write %d failed\n", i); exit(1); } len -= i; curoff += i; } prevlen = curlen; prevoff = curoff; return; bad2: type++; bad1: fprintf(stderr, "Distance between two changes larger than %dK %d %d %d\n", MAX_CHANGE / 1024, type, curoff + j, lastv[type]); exit(1); } int main(int argc, char **argv) { FILE *g, *h; int reloc = SMALL_RELOC; int first_start, first_end, second_start, second_end; int end, rodata_start, rodata_end; int net = 0; int i = 1; char sym[256]; unsigned int addr; if (!strcmp (argv[i], "-a")) { net = 1; i++; } f = fopen(argv[i++], "r"); while (fgets (buffer, 256, f)) { char sym[256]; unsigned int addr; if (sscanf(buffer, "%x %*c %s\n", &addr, sym) == 2) { if (!strcmp (sym, "start")) reloc = addr; else if (!strcmp (sym, "main_text_start")) first_start = addr - reloc; else if (!strcmp (sym, "main_text_end")) first_end = addr - reloc; else if (!strcmp (sym, "main_data_start")) second_start = addr - reloc; else if (!strcmp (sym, "main_data_end")) second_end = addr - reloc; else if (!strcmp (sym, "main_rodata_start")) rodata_start = addr - reloc; else if (!strcmp (sym, "main_rodata_end")) rodata_end = addr - reloc; else if (!strcmp (sym, "__bss_start")) end = addr - reloc; } } fclose (f); f = fopen(argv[i++], "r"); e = fopen(argv[i++], "r"); g = fopen(argv[i++], "w"); h = fopen(argv[i++], "w"); if (fread(buffer, 1, 32, f) != 32) exit(1); if (fread(buffer2, 1, 32, e) != 32) exit(1); if (memcmp(buffer, buffer2, 32)) { fprintf(stderr, "Strange. Images for 2.5MB and 3.5MB differ in a.out header\n"); exit(1); } if (!net) { memset (buffer, 0, 2048); if (fwrite(buffer, 1, 2048, g) != 2048) exit(1); } else { if (fwrite (buffer, 1, 32, g) != 32) exit(1); } save (g, first_start, 0); save (h, first_end - first_start, 2); save (g, rodata_start - first_end, 0); save (h, rodata_end - rodata_start, 2); save (g, second_start - rodata_end, 0); save (h, second_end - second_start, 2); save (g, end - second_end, 0); fwrite(diffs[0], 2, ndiffs[0]+1, g); fwrite(diffs[1], 2, ndiffs[1]+1, g); fwrite(diffs[2], 2, ndiffs[2]+1, h); fwrite(diffs[3], 2, ndiffs[3]+1, h); fclose (f); fclose (e); fclose (g); fclose (h); exit (0); } .