home *** CD-ROM | disk | FTP | other *** search
- /* vi:set tabstop=3: */
- #include <stdio.h>
- #include <st-out.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <sgtty.h>
-
- #define MAX_LISP_TYPE 25
- #define PTRBITS 0x00FFFFFFL
- #define FUZZY 1024 /* difference accepted if in range +- FUZZY */
-
- extern long _stksize = -1L;
-
- int no_questions = 0;
- int overwrite = 0;
- int no_warnings = 0;
-
- unsigned char *reloc_buffer;
-
- void
- add_rel(int n, int i)
- {
- reloc_buffer = (unsigned char *) realloc(reloc_buffer, i+1);
- if(!reloc_buffer) {
- fprintf(stderr, "Unable to allocate %d bytes\n", i+1);
- exit(4);
- }
- reloc_buffer[i] = n;
- }
-
- unsigned char *copy_buffer;
-
- void
- warning(int pos, int i, int j)
- {
- if(!no_warnings) fprintf(stderr, "Unexpected difference @%d: %08X (basediff %08X)\tmemory: %06X\n", pos, i, j, &(copy_buffer[pos - A_TXTOFF(hdr)]));
- }
-
- char known_types[128];
-
- int
- make_emacs(int file1, FILE *file2, int file3)
- {
- struct aexec hdr;
- long base1, base2;
- int i;
- long pos;
- union {
- long i;
- struct {
- unsigned int gc_bit:1;
- unsigned int type:7;
- unsigned int ptr:24;
- } o;
- } val1, val2;
- int offset;
- int start_offset;
- long basediff;
- int diff;
- int fuzzy_relocs = 0;
- int swap_files = 0;
- char ch;
-
- printf("reading dump headers\n");
- fseek(file2, 0, SEEK_SET);
- fread(&hdr, sizeof(struct aexec), 1, file2);
- if(hdr.a_magic != 0x4544) return(2);
- base2 = hdr.a_AZero1;
- lseek(file1, 0, SEEK_SET);
- read(file1, &hdr, sizeof(struct aexec));
- if(hdr.a_magic != 0x4544) return(1);
- base1 = hdr.a_AZero1;
- basediff = base1 - base2;
- if(!basediff) {
- fprintf(stderr, "Files must not have same basepage address\n");
- exit(5);
- }
- if(basediff < 0) {
- basediff = -basediff;
- swap_files = 1;
- }
- base1 += 0x100; /* sizeof(BASEPAGE) */
- hdr.a_AZero1 = 0;
- hdr.a_magic = 0x601A;
- printf("writing corrected header\n");
- printf("data start = %d\n", A_DATOFF(hdr));
- lseek(file3, 0, SEEK_SET);
- write(file3, &hdr, sizeof(struct aexec));
- printf("reading text and data\n");
- copy_buffer = (unsigned char *) malloc(A_STROFF(hdr) - A_TXTOFF(hdr));
- read(file1, copy_buffer, A_STROFF(hdr) - A_TXTOFF(hdr));
- printf("adding new relocation info for dumped data\n");
- pos = A_TXTOFF(hdr);
- start_offset = offset = 0;
- i = -1;
- while(pos < A_STROFF(hdr)) {
- val1.i = *(long *)(&(copy_buffer[pos - A_TXTOFF(hdr)]));
- fseek(file2, pos, SEEK_SET);
- fread(&val2.i, sizeof(long), 1, file2);
- diff = swap_files ? val2.i - val1.i : val1.i - val2.i;
- if(diff == basediff) {
- diff_ok:
- known_types[val1.o.type] = 1;
- if(!(i % 1000)) {
- printf("%4d %6d\r",i,pos);
- fflush(stdout);
- }
- val1.i -= base1;
- *(long *)(&(copy_buffer[pos - A_TXTOFF(hdr)])) = val1.i;
- if(!start_offset) start_offset = offset;
- else {
- while(offset > 254) {
- add_rel(1,++i);
- offset -= 254;
- }
- add_rel(offset,++i);
- }
- offset = 4;
- pos += 4;
- } else if((diff < basediff + FUZZY) &&
- (diff > basediff - FUZZY)) {
- fuzzy_relocs++;
- goto diff_ok;
- } else {
- if(diff && !no_questions) {
- if(diff & 0xFFFF0000L) {
- warning(pos,diff,basediff);
- if(!(val1.o.ptr & 1L) &&
- val1.o.type <= MAX_LISP_TYPE) {
- if(!overwrite || !no_warnings)
- printf(" val1 = %08X, val2 = %08X,\n"
- "base1 = %08X, base2 = %08X,\n"
- " top1 = %08X relocate ? (y|n) "
- ,val1.i,val2.i
- ,base1,base2
- ,base1+A_STROFF(hdr)-sizeof(hdr)+0x100);
- fflush(stdout);
- if(val1.o.ptr >= base1 &&
- val1.o.ptr <= base1 +
- A_STROFF(hdr) -
- sizeof(hdr) +
- 0x100) {
- if(overwrite) {
- if(!no_warnings) printf("Y\n");
- fuzzy_relocs++;
- goto diff_ok;
- }
- ch = getchar();
- printf("\n");
- if(ch == 'Y' || ch == 'y') {
- fuzzy_relocs++;
- goto diff_ok;
- }
- printf("... ignored\n");
- } else if(!overwrite || !no_warnings) {
- printf("N (outside of program)\n");
- }
- }
- }
- }
- offset += 2;
- pos += 2;
- }
- }
- add_rel(0,++i);
- printf("last info was at position %d\n",pos);
- printf("writing text and data\n");
- write(file3, copy_buffer, A_STROFF(hdr) - A_TXTOFF(hdr));
- free(copy_buffer);
- write(file3, &start_offset, sizeof(long));
- printf("writing %d bytes of relocation info", i+1);
- if(fuzzy_relocs) printf(" (%d bytes guessed)", fuzzy_relocs);
- printf("\n");
- lseek(file3, A_STROFF(hdr) + sizeof(long), SEEK_SET);
- write(file3, reloc_buffer, i+1);
- free(reloc_buffer);
- printf("Used tag-fields for pointers:\t");
- for(i = 0; i < 127; i++) if(known_types[i]) printf("%3d ", i);
- printf("\n");
- return(0);
- }
-
- void
- main(int argc, char *argv[])
- {
- FILE *file2;
- int file1, file3;
- int error;
- struct sgttyb sg;
- char *prg_name;
-
- gtty(0,&sg);
- sg.sg_flags |= CBREAK;
- stty(0,&sg);
- printf("Relocation fix for emacs dump files\n");
- prg_name = argv[0];
- while(argc > 1 && argv[1][0] == '-') {
- switch(argv[1][1]) {
- case 'n' : no_questions = 1; break;
- case 'o' : overwrite = 1; break;
- case 'w' : no_warnings = 1; break;
- }
- argc--;
- argv++;
- }
- if(argc < 4) {
- fprintf(stderr, "Usage: %s [-n] [-o] [-w] dump1 dump2 executable\n", prg_name);
- exit(3);
- }
- if(file1 = open(argv[1],0)) {
- if(file2 = fopen(argv[2],"rb")) {
- setvbuf(file2, NULL, _IOFBF, 10240);
- if(file3 = creat(argv[3],0666)) {
- switch(error = make_emacs(file1,file2,file3)) {
- case 1 :
- fprintf(stderr,
- "%s: Not an emacs dump file",
- argv[1]);
- case 2 :
- fprintf(stderr,
- "%s: Not an emacs dump file",
- argv[2]);
- break;
- }
- close(file3);
- } else perror(argv[3]);
- fclose(file2);
- } else perror(argv[2]);
- close(file1);
- } else perror(argv[1]);
- exit(error);
- }
-