/* * dohunk.c - Do hunk output & relocation for unhunk program. * Copyright 1986 by Eric D. Black. * Permission is given to redistribute this program * and its source code subject to the * restrictions given in the file "unhunk.c" * */ #include #include "convert.h" #include "hunk.h" #include "bin.out.h" #ifdef DBUG #include #else #include "dbugstubs.h" #endif /* hunk information */ extern Hinfo **hunk; /* -> vector of ptrs to Hinfo structs */ extern Hinfo *firsthunk; /* -> first hunk */ extern int nhunks; /* #hunks in input file */ extern int curhunk; /* current hunk# */ extern int hvalid; /* state variable (to bump curhunk) */ extern long filpos; /* position in input file */ extern long siz[3]; /* segment sizes */ extern long maxhunk; /* size of biggest hunk found */ extern long *hunkbuf; /* -> buffer for doing hunk relocation */ extern char *secname; /* "Text", "Data", "BSS" section name strs */ /* * Generate memory image file from hunk format load file and * information collected into Hinfo structs by 1st pass in convert() */ output(ifd, ofd) int ifd, ofd; { struct bin bin_hd; int i; Hinfo *hu; DBUG_ENTER("output"); /* * Write header, then hunks to output file in sorted order; * for each hunk, read it into buffer, read relocation * info & do relocation; then write buffer to output file */ bin_hd.b_magic = BMAGIC; bin_hd.b_text = siz[TEXT]; bin_hd.b_data = siz[DATA]; bin_hd.b_bss = siz[BSS]; bin_hd.b_txorg = origin[TEXT]; bin_hd.b_dtorg = origin[DATA]; bin_hd.b_bsorg = origin[BSS]; bin_hd.b_entry = entrypnt; for (i=0; i<8; i++) bin_hd.b_rsrv[i] = 0; if (write(ofd, &bin_hd, sizeof(bin_hd)) != sizeof(bin_hd)) { panic("Can't write output file\n"); } DBUG_3("mem","malloc'ing %d bytes for hunkbuf", maxhunk); if ((hunkbuf = (long *)malloc((int)maxhunk)) == NULL) allerr(); for (hu = firsthunk; hu != NULL; hu = hu->hnext) if (hu->htype == TEXT || hu->htype == DATA) { lseek(ifd, hu->hpos, 0); /* get hunk */ if (read(ifd, hunkbuf, (int)hu->hsize) != (int)hu->hsize) panic("Error reading input file."); DBUG_4("rel","hunk %d, %ld bytes", hu->hunkno, (int)hu->hsize); /* * relocate hunk in buffer */ if(hu->hsize) { /* for nonzero-size hunks */ reloc(hunkbuf, ifd, hu); /* relocate hunk */ if (write(ofd, hunkbuf, (int)hu->hsize) != (int)hu->hsize) panic("Error writing output file."); } else { DBUG_3("rel","hunk %d zero length", hu->hunkno); } } DBUG_2("mem", "freeing hunkbuf"); free(hunkbuf); DBUG_RETURN(0); } /* * Read relocation records from input hunk file, perform relocation * on hunk in buffer */ reloc(buffer, fd, hp) char *buffer; int fd; Hinfo *hp; { long pos; long hunksize; long numoffset; long hunknum; long reloffset; Hinfo *h; DBUG_ENTER("reloc"); pos = hp->hrel; if(pos==0L) { DBUG_2("rel", "no relocation info for this hunk"); DBUG_RETURN(0); } hunksize = hp->hsize; DBUG_4("rel","reloc start filepos %ld, buffer at 0x%lx", pos, buffer); lseek(fd, pos, 0); /* go to 1st relocation record this hunk */ do { getlong(fd, &numoffset); /* get # of offsets to relocate */ DBUG_3("rel","%ld offsets", numoffset); if (numoffset) { getlong(fd, &hunknum); /* add address of this hunk ... */ if((int)hunknum > nhunks) { printf("Bad hunk # in relocation info: %d, nhunks=%d\n", hunknum, nhunks); panic("phase error"); } h = hunk[hunknum]; DBUG_4("rel"," hunk %ld (base=0x%lx)",hunknum,h->haddr); while(numoffset--) { getlong(fd, &reloffset); /* ... to word at this offset */ DBUG_5("rel"," offset 0x%lx (addr 0x%lx) = 0x%lx",reloffset,buffer+reloffset,*(long *)(buffer+reloffset)); if(reloffset>hunksize-3) { fprintf(stderr, "Unreasonable relocation offset 0x%lx in %s hunk %d", reloffset, secname[h->htype], h->hunkno); panic("Input file possibly garbled"); } /* * Add base address of specified hunk to the contents of * longword at specified byte offset * (isn't the combination of bytes & longwords clear??) */ *(long *)(buffer+reloffset) += h->haddr; DBUG_3("rel"," new contents = 0x%lx", *(long *)(buffer+reloffset)); } } } while (numoffset); DBUG_RETURN(0); }