From 4737cb56bcc1488965d3901055cc688eee8d4758 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 29 Jun 2016 17:41:56 +0100 Subject: [PATCH] ld09: updates --- Applications/ld09/Makefile.z80 | 5 +- Applications/ld09/mkar.c | 169 ++++++----- Applications/ld09/objdump86.c | 138 ++++----- Applications/ld09/writefuzix.c | 502 +++++++++++++++++++++++++++++++++ 4 files changed, 655 insertions(+), 159 deletions(-) create mode 100644 Applications/ld09/writefuzix.c diff --git a/Applications/ld09/Makefile.z80 b/Applications/ld09/Makefile.z80 index a8f90c00..f859d4d7 100644 --- a/Applications/ld09/Makefile.z80 +++ b/Applications/ld09/Makefile.z80 @@ -8,11 +8,14 @@ DEFS = OBJS= dumps.rel io.rel ld.rel readobj.rel table.rel typeconv.rel linksyms.rel \ writefuzix.rel -all: ld09 +all: ld09 mkar ld09: $(OBJS) $(CC) -o $@ $(OBJS) +mkar: mkar.rel + $(CC) -o $@ $< + clean realclean clobber: rm -f *.rel *.lst *.sym *.asm ld09 ld09r objchop catimage objdump09 *~ *.bin *.lk *.map *.noi diff --git a/Applications/ld09/mkar.c b/Applications/ld09/mkar.c index 2ca98554..622f19d6 100644 --- a/Applications/ld09/mkar.c +++ b/Applications/ld09/mkar.c @@ -1,85 +1,108 @@ #include #include -#include -#include -#ifdef __STDC__ #include #include -#else -#include -#endif +#include +#include +#include +#include -#include "type.h" #include "ar.h" static struct ar_hdr arbuf; -#ifdef __STDC__ -void -ld86r(int argc, char ** argv) -#else -ld86r(argc, argv) - int argc; char ** argv; -#endif +static char buf[512]; +static const char *path; +static char space = ' '; + +static void twrite(int fd, const void *p, int len) +{ + if (write(fd, p, len) != len) + err(1, "%s: write failed", path); +} + +static void copy_file(const char *p, int fd) +{ + int ifd; + ssize_t l; + + if ((ifd = open(p, O_RDONLY)) == -1) { + perror(p); + exit(1); + } + while ((l = read(ifd, buf, sizeof(buf))) > 1) + twrite(fd, buf, l); + if (l == 1) + twrite(fd, &space, 1); + if (l == -1) { + perror("read"); + exit(1); + } + close(ifd); +} + +int main(int argc, char *argv[]) { -char buf[128]; - FILE * fd, * ifd; - struct stat st; - int ar, libarg=0, need_o = 0, got_o = 0; - - for(ar=1; ar 1 || need_o > got_o ) - fatalerror("-o option required for -r"); - - if( (fd =fopen(argv[libarg], "wb")) == 0 ) fatalerror("Cannot open archive"); - if( fwrite(ARMAG, 1, SARMAG, fd) != SARMAG) fatalerror("Cannot write magic"); - - for(ar=1; ar 1 || need_o > got_o) + errx(1, "-o option required for -r"); + + path = argv[libarg]; + + if ((fd = open(path, O_WRONLY)) == -1) + err(1, "unable to open %s", path); + + + twrite(fd, ARMAG, SARMAG); + + for (ar = 1; ar < argc; ar++) { + if (ar != libarg && argv[ar][0] != '-') { + char *ptr; + if (stat(argv[ar], &st) < 0) + err(1, "cannot stat object %s", argv[ar]); + if ((ptr = strrchr(argv[ar], '/'))) + ptr++; + else + ptr = argv[ar]; + memset(&arbuf, ' ', sizeof(arbuf)); + snprintf(buf, sizeof(buf), "%s/ ", ptr); + strncpy(arbuf.ar_name, buf, sizeof(arbuf.ar_name)); + + snprintf(arbuf.ar_date, 12, "%-12ld", + (long) st.st_mtime); + snprintf(arbuf.ar_uid, 6, "%-6d", + (int) (st.st_uid % 1000000L)); + snprintf(arbuf.ar_gid, 6, "%-6d", + (int) (st.st_gid % 1000000L)); + snprintf(arbuf.ar_mode, 8, "%-8lo", + (long) st.st_mode); + snprintf(arbuf.ar_size, 10, "%-10ld", + (long) st.st_size); + memcpy(arbuf.ar_fmag, ARFMAG, + sizeof(arbuf.ar_fmag)); + + twrite(fd, &arbuf, sizeof(arbuf)); + copy_file(argv[ar], fd); + } + } + close(fd); + exit(0); } diff --git a/Applications/ld09/objdump86.c b/Applications/ld09/objdump86.c index 89f4e2da..f73d820e 100644 --- a/Applications/ld09/objdump86.c +++ b/Applications/ld09/objdump86.c @@ -13,48 +13,40 @@ * * Copyright (c) 1999 by Greg Haerr * Added archive file reading capabilties + * + * Modified for Fuzix by Alan Cox 2016. */ #include -#ifdef __STDC__ #include -#else -#include -#endif #include #include "const.h" #include "ar.h" #include "obj.h" -FILE * ifd; -char * ifname; - -#ifdef __STDC__ -#define _(x) x -#else -#define _(x) () -#endif - -long get_long _((void)); -long get_sized _((int sz)); -unsigned int get_word _((void)); -int get_byte _((void)); -int main _((int argc, char**argv)); -void do_file _((char * fname)); -long read_arheader _((char *archentry)); -void do_module _((char * fname, char *archive)); -int error _((char * str)); -int read_objheader _((void)); -int read_sectheader _((void)); -int read_syms _((void)); -void disp_sectheader _((void)); -int disp_syms _((void)); -void read_databytes _((void)); -void hex_output _((int ch)); -void fetch_aout_hdr _((void)); -void dump_aout _((void)); -void size_aout _((void)); -void nm_aout _((void)); +FILE *ifd; +char *ifname; + +long get_long(void); +long get_sized(int sz); +unsigned int get_word(void); +int get_byte(void); +int main(int argc, char**argv); +void do_file(char * fname); +long read_arheader(char *archentry); +void do_module(char * fname, char *archive); +int error(char * str); +int read_objheader(void); +int read_sectheader(void); +int read_syms(void); +void disp_sectheader(void); +int disp_syms(void); +void read_databytes(void); +void hex_output(int ch); +void fetch_aout_hdr(void); +void dump_aout(void); +void size_aout(void); +void nm_aout(void); int obj_ver; int sections; @@ -84,10 +76,7 @@ int opt_o; long size_text, size_data, size_bss; long tot_size_text=0, tot_size_data=0, tot_size_bss=0; -int -main(argc, argv) -int argc; -char ** argv; +int main(int argc, char *argv[]) { int ar; char * p; @@ -132,9 +121,7 @@ char ** argv; return 0; } -void -do_file(fname) -char * fname; +void do_file(char * fname) { unsigned int magic; long filelength; @@ -178,9 +165,7 @@ char * fname; } /* read archive header and return length */ -long -read_arheader(archentry) -char *archentry; +long read_arheader(char *archentry) { char * endptr; struct ar_hdr arheader; @@ -197,10 +182,7 @@ char *archentry; return strtoul(arheader.ar_size, (char **)NULL, 0); } -void -do_module(fname, archive) -char * fname; -char * archive; +void do_module(char *fname, char *archive) { int modno, i; @@ -285,9 +267,7 @@ char * archive; symnames = 0; } -int -error(str) -char * str; +int error(char *str) { switch( display_mode ) { @@ -300,14 +280,14 @@ char * str; return -1; } -int -read_objheader() +int read_objheader(void) { unsigned char buf[5]; if( fread(buf, 1, 5, ifd) != 5 ) return error("Cannot read object header"); - +#if 0 + /* FIXME: Fuzix not ELKS support needed */ if( buf[0] != 0xA3 || buf[1] != 0x86 ) { if( buf[0] == 1 && buf[1] == 3 ) @@ -317,7 +297,7 @@ read_objheader() } return error("Bad magic number"); } - +#endif if( (unsigned char)(buf[0] + buf[1] + buf[2] + buf[3]) != buf[4] ) return error("Bad header checksum"); @@ -326,8 +306,7 @@ read_objheader() return 0; } -int -read_sectheader() +int read_sectheader(void) { long ssenc; int i; @@ -353,8 +332,7 @@ read_sectheader() return 0; } -void -disp_sectheader() +void disp_sectheader(void) { int i; if( display_mode ) return; @@ -373,13 +351,13 @@ disp_sectheader() printf("SYMS %u\n", num_syms); } -int -read_syms() +int read_syms(void) { int i; if( num_syms < 0 ) return error("Bad symbol table"); + /* FIXME: overflows */ symnames = malloc(num_syms*sizeof(char*)+1); if( symnames == 0 ) return error("Out of memory"); @@ -407,8 +385,7 @@ read_syms() return 0; } -int -disp_syms() +int disp_syms(void) { int i; @@ -482,10 +459,10 @@ disp_syms() return 0; } -void -read_databytes() -{ static char * relstr[] = {"ERR", "DB", "DW", "DD"}; + +void read_databytes(void) +{ long l, cpos; int ch, i; int curseg = 0; @@ -568,9 +545,7 @@ break_break:; fseek(ifd, cpos, 0); } -long -get_sized(sz) -int sz; +long get_sized(int sz) { switch(sz) { @@ -582,8 +557,7 @@ int sz; return -1; } -long -get_long() +long get_long(void) { long retv = 0; int i; @@ -598,8 +572,7 @@ get_long() return retv; } -unsigned int -get_word() +unsigned int get_word(void) { long retv = 0; int i; @@ -616,8 +589,7 @@ get_word() return retv; } -int -get_byte() +int get_byte(void) { int v = getc(ifd); if (v == EOF) return -1; @@ -625,9 +597,7 @@ get_byte() return v; } -void -hex_output(ch) -int ch; +void hex_output(int ch) { static char linebuf[80]; static char buf[20]; @@ -658,13 +628,14 @@ static int pos = 0; /************************************************************************/ /* ELKS a.out versions + * + * TODO: Fuzix headers */ long header[12]; int h_len, h_flgs, h_cpu; -void -fetch_aout_hdr() +void fetch_aout_hdr(void) { int i; @@ -685,8 +656,7 @@ fetch_aout_hdr() } } -void -dump_aout() +void dump_aout(void) { static char * cpu[] = { "unknown", "8086", "m68k", "ns16k", "i386", "sparc" }; static char * byteord[] = { "LITTLE_ENDIAN", "(2143)","(3412)","BIG_ENDIAN" }; @@ -756,8 +726,7 @@ static char * byteord[] = { "LITTLE_ENDIAN", "(2143)","(3412)","BIG_ENDIAN" }; hex_output(EOF); } -void -size_aout() +void size_aout(void) { if( display_mode == 0 ) printf("text\tdata\tbss\tdec\thex\tfilename\n"); @@ -773,8 +742,7 @@ size_aout() tot_size_bss += header[4]; } -void -nm_aout() +void nm_aout(void) { char n_name[10]; long n_value; diff --git a/Applications/ld09/writefuzix.c b/Applications/ld09/writefuzix.c new file mode 100644 index 00000000..c842bd65 --- /dev/null +++ b/Applications/ld09/writefuzix.c @@ -0,0 +1,502 @@ + +/* writefuzix.c - write binary file for linker */ + +/* Based upon writebin Copyright (C) 1994 Bruce Evans */ + +/* + * TODO + * - add support for debug symbol tables + * - figure out how banked binaries should look + * - add a discard segment that is put between data and bss and the + * bss size shrunk by its size (so the bootstrap code jumps to discard, + * relocates and then it gets wiped) + */ + +#include "syshead.h" +#include "bindef.h" +#include "const.h" +#include "obj.h" +#include "type.h" +#include "globvar.h" + +#define btextoffset (text_base_value) +#define bdataoffset (data_base_value) + +struct fuzix16_hdr { + uint8_t jmp; + uint16_t addr; + uint8_t magic[4]; + uint8_t load; + uint16_t chmem; + uint16_t code; + uint16_t data; + uint16_t bss; + uint16_t mbz; + /* Header can be extended as the jump goes over it */ +}; + +#define HEADERSIZE sizeof(struct fuzix16_hdr) +/* It's part of the binary */ +#define FILEHEADERLENGTH 0 +/* Must match AS09 */ +#define DPSEG 3 + +#define CM_MASK 0xC0 +#define MODIFY_MASK 0x3F +#define S_MASK 0x04 +#define OF_MASK 0x03 + +#define CM_SPECIAL 0 +#define CM_ABSOLUTE 0x40 +#define CM_OFFSET_RELOC 0x80 +#define CM_SYMBOL_RELOC 0xC0 + +#define CM_EOT 0 +#define CM_BYTE_SIZE 1 +#define CM_WORD_SIZE 2 +#define CM_LONG_SIZE 3 +#define CM_1_SKIP 17 +#define CM_2_SKIP 18 +#define CM_4_SKIP 19 +#define CM_0_SEG 32 + +#define ABS_TEXT_MAX 64 + +#define memsizeof(struc, mem) sizeof(((struc *) 0)->mem) + +static bool_t bits32; /* nonzero for 32-bit executable */ +static bin_off_t combase[NSEG];/* bases of common parts of segments */ +static bin_off_t comsz[NSEG]; /* sizes of common parts of segments */ +static fastin_t curseg; /* current segment, 0 to $F */ +static bin_off_t edataoffset; /* end of data */ +static bin_off_t endoffset; /* end of bss */ +static bin_off_t etextoffset; /* end of text */ +static bin_off_t etextpadoff; /* end of padded text */ +static unsigned nsym; /* number of symbols written */ +static unsigned relocsize; /* current relocation size 1, 2 or 4 */ +static bin_off_t segadj[NSEG]; /* adjusts (file offset - seg offset) */ + /* depends on zero init */ +static bin_off_t segbase[NSEG];/* bases of data parts of segments */ +static char segboundary[9] = "__seg0DH"; + /* name of seg boundary __seg0DL to __segfCH */ +static bin_off_t segpos[NSEG]; /* segment positions for current module */ +static bin_off_t segsz[NSEG]; /* sizes of data parts of segments */ + /* depends on zero init */ +static bool_t stripflag; /* nonzero to strip symbols */ +static bin_off_t spos; /* position in current seg */ +static bool_t uzp; /* nonzero for unmapped zero page */ +static bool_t sepid; /* Separate I & D space (8086 etc) */ + +static void linkmod(struct modstruct *modptr); +static void padmod(struct modstruct *modptr); +static void setsym(char *name, bin_off_t value); +static void symres(char *name); +static void setseg(fastin_pt newseg); +static void skip(unsigned countsize); +static void writeheader(void); +static void writenulls(bin_off_t count); + +void write_fuzix(char *outfilename, bool_pt argsepid, bool_pt argbits32, + bool_pt argstripflag, bool_pt arguzp) +{ + char *cptr; + struct modstruct *modptr; + fastin_t seg; + unsigned sizecount; + bin_off_t tempoffset; + + sepid = argsepid; + bits32 = argbits32; + stripflag = argstripflag; + uzp = arguzp; + + /* reserve special symbols use curseg to pass parameter to symres() */ + for (curseg = 0; curseg < NSEG; ++curseg) + { + segboundary[5] = hexdigit[curseg]; /* to __segX?H */ + segboundary[6] = 'D'; + symres(segboundary); /* __segXDH */ + segboundary[7] = 'L'; + symres(segboundary); /* __segXDL */ + segboundary[6] = 'C'; + symres(segboundary); /* __segXCL */ + segboundary[7] = 'H'; + symres(segboundary); /* __segXCH */ +#ifndef DATASEGS + if( curseg > 3 ) + { + segboundary[6] = 'S'; + segboundary[7] = 'O'; + symres(segboundary); /* __segXSO */ + } +#endif + } + /* FIXME: we need a BSS segment in here ??? */ + curseg = 3; + symres("__edata"); + symres("__end"); + curseg = 0; /* text seg, s.b. variable */ + symres("__etext"); + symres("__segoff"); + + /* calculate segment and common sizes (sum over loaded modules) */ + /* use zero init of segsz[] */ + /* also relocate symbols relative to starts of their segments */ + for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NUL_PTR; ++symparray) + if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) + { + if (!(symptr->flags & (I_MASK | SA_MASK))) + { + /* relocate by offset of module in segment later */ + /* relocate by offset of segment in memory special */ + /* symbols get relocated improperly */ + symptr->value += segsz[symptr->flags & SEGM_MASK]; + } + else if (symptr->value == 0) + undefined(symptr->name); + else + { + tempoffset = ld_roundup(symptr->value, 4, bin_off_t); + /* temp kludge quad alignment for 386 */ + symptr->value = comsz[seg = symptr->flags & SEGM_MASK]; + comsz[seg] += tempoffset; + if (!(symptr->flags & SA_MASK)) + symptr->flags |= C_MASK; + } + } + for (seg = 0, cptr = modptr->segsize; seg < NSEG; ++seg) + { + segsz[seg] += cntooffset(cptr, + sizecount = segsizecount((unsigned) seg, modptr)); + cptr += sizecount; + } + } + + /* calculate seg positions now their sizes are known */ + /* temp use fixed order 0D 0C 1D 1C 2D 2C ... */ + /* +#ifdef DATASEGS + * Assume seg 0 is text and rest are data +#else + * Assume seg 1..3 are data, Seg 0 is real text, seg 4+ are far text +#endif + */ + segpos[0] = segbase[0] = spos = btextoffset; + combase[0] = segbase[0] + segsz[0]; + segadj[1] = segadj[0] = -btextoffset; + etextpadoff = etextoffset = combase[0] + comsz[0]; + /* No rounding needed currently - but keep for x86 etc when we get + to them */ +#if 0 + if (sepid) + { + etextpadoff = ld_roundup(etextoffset, 0x10, bin_off_t); + segadj[1] += etextpadoff - bdataoffset; + } else +#endif + if (bdataoffset == 0) + bdataoffset = etextpadoff; + segpos[1] = segbase[1] = edataoffset = bdataoffset; + combase[1] = segbase[1] + segsz[1]; +#ifndef DATASEGS + for (seg = 4; seg < NSEG; ++seg) + { + segpos[seg] = segbase[seg] = 0; + combase[seg] = segbase[seg] + segsz[seg]; + segadj[seg] = etextpadoff; + + etextpadoff += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t); + segadj[1] += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t); + } + for (seg = 2; seg < 4; ++seg) +#else + for (seg = 2; seg < NSEG; ++seg) +#endif + { + segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1]; +#if defined(MC6809) || defined(MC6502) + if (seg == DPSEG) + { + /* temporarily have fixed DP seg */ + /* adjust if nec so it only spans 1 page */ + tempoffset = segsz[seg] + comsz[seg]; + if (tempoffset > 0x100) + fatalerror("direct page segment too large"); + if ((((segbase[seg] + tempoffset) ^ segbase[seg]) + & ~(bin_off_t) 0xFF) != 0) + segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF) + & ~(bin_off_t) 0xFF; + } +#endif + + combase[seg] = segbase[seg] + segsz[seg]; + segadj[seg] = segadj[seg - 1]; + } + + /* relocate symbols by offsets of segments in memory */ + for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NUL_PTR; ++symparray) + if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) + { + if (symptr->flags & (C_MASK | SA_MASK)) + symptr->value += combase[symptr->flags & SEGM_MASK]; + else + symptr->value += segbase[symptr->flags & SEGM_MASK]; + } + } + + /* adjust special symbols */ + for (seg = 0; seg < NSEG; ++seg) + { +#ifdef DATASEGS + if (segsz[seg] != 0) + /* only count data of nonzero length */ +#else + if (segsz[seg] != 0 && seg < 4) +#endif + edataoffset = segbase[seg] + segsz[seg]; + segboundary[5] = hexdigit[seg]; /* to __segX?H */ + segboundary[6] = 'D'; + setsym(segboundary, (tempoffset = segbase[seg]) + segsz[seg]); + /* __segXDH */ + segboundary[7] = 'L'; + setsym(segboundary, tempoffset); /* __segXDL */ + segboundary[6] = 'C'; + setsym(segboundary, tempoffset = combase[seg]); + /* __segXCL */ + segboundary[7] = 'H'; + setsym(segboundary, tempoffset + comsz[seg]); + /* __segXCH */ +#ifndef DATASEGS + if( seg > 3 ) + { + segboundary[6] = 'S'; + segboundary[7] = 'O'; + setsym(segboundary, (bin_off_t)(segadj[seg]-segadj[0])/0x10); + /* __segXSO */ + } +#endif + } + setsym("__etext", etextoffset); + setsym("__edata", edataoffset); +#ifdef DATASEGS + setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]); +#else + setsym("__end", endoffset = combase[3] + comsz[3]); +#endif + setsym("__segoff", (bin_off_t)(segadj[1]-segadj[0])/0x10); + if( !bits32 ) + { + if( etextoffset > 65536L ) + fatalerror("text segment too large for 16bit"); + if( endoffset > 65536L ) + fatalerror("data segment too large for 16bit"); + } + + openout(outfilename); + writeheader(); + for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) { if (modptr->loadflag) + { + linkmod(modptr); + padmod(modptr); + } + } + closeout(); + executable(); +} + +static void linkmod(struct modstruct *modptr) +{ + char buf[ABS_TEXT_MAX]; + int command; + unsigned char modify; + bin_off_t offset; + int symbolnum; + struct symstruct **symparray; + struct symstruct *symptr; + + setseg(0); + relocsize = 2; + symparray = modptr->symparray; + openin(modptr->filename); /* does nothing if already open */ + seekin(modptr->textoffset); + while (TRUE) + { + if ((command = readchar()) < 0) + prematureeof(); + modify = command & MODIFY_MASK; + switch (command & CM_MASK) + { + case CM_SPECIAL: + switch (modify) + { + case CM_EOT: + segpos[curseg] = spos; + return; + case CM_BYTE_SIZE: + relocsize = 1; + break; + case CM_WORD_SIZE: + relocsize = 2; + break; + case CM_LONG_SIZE: +#ifdef LONG_OFFSETS + relocsize = 4; + break; +#else + fatalerror("relocation by long offsets not implemented"); +#endif + case CM_1_SKIP: + skip(1); + break; + case CM_2_SKIP: + skip(2); + break; + case CM_4_SKIP: + skip(4); + break; + default: + if ((modify -= CM_0_SEG) >= NSEG) + inputerror("bad data in"); + setseg(modify); + break; + } + break; + case CM_ABSOLUTE: + if (modify == 0) + modify = ABS_TEXT_MAX; + readin(buf, (unsigned) modify); + writeout(buf, (unsigned) modify); + spos += (int) modify; + break; + case CM_OFFSET_RELOC: + offset = readsize(relocsize); + if (modify & R_MASK) + { +#ifndef DATASEGS + int m = (modify & SEGM_MASK); + if( curseg != m && m != SEGM_MASK ) + interseg(modptr->filename, modptr->archentry, (char*)0); +#endif + offset -= (spos + relocsize); + } + offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize); + writeout(buf, relocsize); + spos += relocsize; + break; + case CM_SYMBOL_RELOC: + symptr = symparray[symbolnum = readconvsize((unsigned) + (modify & S_MASK ? 2 : 1))]; + offset = readconvsize((unsigned) modify & OF_MASK); + if (modify & R_MASK) + { +#ifndef DATASEGS + int m = (symptr->flags & SEGM_MASK); + if( curseg != m && m != SEGM_MASK ) + interseg(modptr->filename, modptr->archentry, symptr->name); +#endif + offset -= (spos + relocsize); + } + offset += symptr->value; + offtocn(buf, offset, relocsize); + writeout(buf, relocsize); + spos += relocsize; + } + } +} + +static void padmod(struct modstruct *modptr) +{ + bin_off_t count; + fastin_t seg; + bin_off_t size; + unsigned sizecount; + char *sizeptr; + + for (seg = 0, sizeptr = modptr->segsize; seg < NSEG; ++seg) + { + size = cntooffset(sizeptr, + sizecount = segsizecount((unsigned) seg, modptr)); + sizeptr += sizecount; + if ((count = segpos[seg] - segbase[seg]) != size) + size_error(seg, count, size); + + /* pad to quad boundary */ + /* not padding in-between common areas which sometimes get into file */ + if ((size = ld_roundup(segpos[seg], 4, bin_off_t) - segpos[seg]) != 0) + { + setseg(seg); + writenulls(size); + segpos[seg] = spos; + } + segbase[seg] = segpos[seg]; + } +} + +static void setsym(char *name, bin_off_t value) +{ + struct symstruct *symptr; + + if ((symptr = findsym(name)) != NUL_PTR) + symptr->value = value; +} + +static void symres(char *name) +{ + register struct symstruct *symptr; + + if ((symptr = findsym(name)) != NUL_PTR) + { + if ((symptr->flags & SEGM_MASK) == SEGM_MASK) + symptr->flags &= ~SEGM_MASK | curseg; + if (symptr->flags != (I_MASK | curseg) || symptr->value != 0) + reserved(name); + symptr->flags = E_MASK | curseg; /* show defined, not common */ + } +} + +/* set new segment */ + +static void setseg(fastin_pt newseg) +{ + if (newseg != curseg) + { + segpos[curseg] = spos; + spos = segpos[curseg = newseg]; + seekout(FILEHEADERLENGTH + (unsigned long) spos + + (unsigned long) segadj[curseg]); + } +} + +static void skip(unsigned countsize) +{ + writenulls((bin_off_t) readsize(countsize)); +} + +static void writeheader(void) +{ +} + +static void writenulls(bin_off_t count) +{ + long lcount = count; + if( lcount < 0 ) + fatalerror("org command requires reverse seek"); + spos += count; + while (count-- > 0) + writechar(0); +} + -- 2.34.1