diff options
Diffstat (limited to 'bin86-0.3/ld/writebin.c')
-rw-r--r-- | bin86-0.3/ld/writebin.c | 949 |
1 files changed, 949 insertions, 0 deletions
diff --git a/bin86-0.3/ld/writebin.c b/bin86-0.3/ld/writebin.c new file mode 100644 index 0000000..56b329d --- /dev/null +++ b/bin86-0.3/ld/writebin.c @@ -0,0 +1,949 @@ +/* + * bin86/ld/writebin.c + * + * Copyright (C) 1992 Bruce Evans + */ + +extern long text_base_address; +#define btextoffset text_base_address +static long bdataoffset; +#define page_size() 4096 + +/* writebin.c - write binary file for linker */ + +#ifdef A_OUT_H +# include A_OUT_H +#else +# ifdef BSD_A_OUT +# include "bsd-a.out.h" +# define A_MINHDR 0 +# define C_EXT N_EXT +# define C_STAT 0 +# define n_was_name n_un.n_name +# define n_was_numaux n_other +# define n_was_other n_numaux +# define n_was_sclass n_type +# define n_was_strx n_un.n_strx +# define n_was_type n_desc +# else /* not BSD_A_OUT */ +# include "a.out.h" /* maybe local copy of <a.out.h> for X-link */ +# define n_was_name n_name +# define n_was_numaux n_numaux +# define n_was_other n_other +# define n_was_sclass n_sclass +# define n_was_strx n_value +# define n_was_type n_type +# endif /* BSD_A_OUT */ +#endif + +#include "const.h" +#include "obj.h" +#include "type.h" +#undef EXTERN +#include "globvar.h" + +#ifdef EDOS +# define FILEHEADERLENGTH 0 +#endif +#ifdef MINIX +# ifdef BSD_A_OUT +# define FILEHEADERLENGTH sizeof (struct exec) +# else +# define FILEHEADERLENGTH A_MINHDR + /* part of header not counted in offsets */ +# endif +#endif +#define DPSEG 2 + +#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 offsetof(struc, mem) ((int) &((struc *) 0)->mem) +#define memsizeof(struc, mem) sizeof(((struc *) 0)->mem) + +PRIVATE bool_t bits32; /* nonzero for 32-bit executable */ +PRIVATE offset_t combase[NSEG]; /* bases of common parts of segments */ +PRIVATE offset_t comsz[NSEG]; /* sizes of common parts of segments */ +PRIVATE char curseg; /* current segment, 0 to $F */ +PRIVATE offset_t edataoffset; /* end of data */ +PRIVATE offset_t endoffset; /* end of bss */ +PRIVATE offset_t etextoffset; /* end of text */ +PRIVATE offset_t etextpadoff; /* end of padded text */ +#ifdef BSD_A_OUT +PRIVATE unsigned ndreloc; /* number of data relocations */ +#endif +PRIVATE unsigned nsym; /* number of symbols written */ +#ifdef BSD_A_OUT +PRIVATE unsigned ntreloc; /* number of text relocations */ +PRIVATE bool_t reloc_output; /* nonzero to leave reloc info in output */ +#endif +PRIVATE unsigned relocsize; /* current relocation size 1, 2 or 4 */ +PRIVATE offset_t segadj[NSEG]; /* adjusts (file offset - seg offset) */ + /* depends on zero init */ +PRIVATE offset_t segbase[NSEG]; /* bases of data parts of segments */ +PRIVATE char segboundary[9] = "__seg0DH"; + /* name of seg boundary __seg0DL to __segfCH */ +PRIVATE offset_t segpos[NSEG]; /* segment positions for current module */ +PRIVATE offset_t segsz[NSEG]; /* sizes of data parts of segments */ + /* depends on zero init */ +PRIVATE bool_t sepid; /* nonzero for separate I & D */ +PRIVATE bool_t stripflag; /* nonzero to strip symbols */ +PRIVATE offset_t spos; /* position in current seg */ +PRIVATE bool_t uzp; /* nonzero for unmapped zero page */ + +#ifdef EDOS +FORWARD unsigned binheaderlength P((char *commandname)); +FORWARD char *idconvert P((struct entrylist *elptr, char *commandname)); +#endif +FORWARD void linkmod P((struct modstruct *modptr)); +FORWARD void linkrefs P((struct modstruct *modptr)); +FORWARD void padmod P((struct modstruct *modptr)); +FORWARD void setsym P((char *name, offset_t value)); +FORWARD void symres P((char *name)); +FORWARD void setseg P((unsigned newseg)); +FORWARD void skip P((unsigned countsize)); +#ifdef EDOS +FORWARD void writeheader P((char *commandname)); +#else +FORWARD void writeheader P((void)); +#endif +FORWARD void writenulls P((offset_t count)); + +/* link all symbols connected to entry symbols */ + +PUBLIC void linksyms(argreloc_output) +bool_pt argreloc_output; +{ + char needlink; + struct entrylist *elptr; + struct modstruct *modptr; + struct symstruct *symptr; + +#ifdef BSD_A_OUT + reloc_output = argreloc_output; + if (argreloc_output) + { + if (modfirst->modnext != NULL) + fatalerror("relocatable output only works for one input file"); + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + modptr->loadflag = TRUE; + return; + } +#endif + if ((symptr = findsym("_main")) != NULL) + entrysym(symptr); + do + { + if ((elptr = entryfirst) == NULL) + fatalerror("no start symbol"); + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + modptr->loadflag = FALSE; + for (; elptr != NULL; elptr = elptr->elnext) + linkrefs(elptr->elsymptr->modptr); + if ((symptr = findsym("start")) != NULL || + (symptr = findsym("crtso")) != NULL) + linkrefs(symptr->modptr); + needlink = FALSE; + { + struct redlist *prlptr; + struct redlist *rlptr; + + for (rlptr = redfirst; rlptr != NULL; + rlptr = (prlptr = rlptr)->rlnext) + if (rlptr->rlmodptr->loadflag && + rlptr->rlmodptr->class > rlptr->rlsymptr->modptr->class) + { + rlptr->rlsymptr->modptr = rlptr->rlmodptr; + rlptr->rlsymptr->value = rlptr->rlvalue; + if (rlptr == redfirst) + redfirst = rlptr->rlnext; + else + prlptr->rlnext = rlptr->rlnext; + needlink = TRUE; + } + } + } + while (needlink); +} + +/* write binary file */ + +PUBLIC void writebin(outfilename, argsepid, argbits32, argstripflag, arguzp) +char *outfilename; +bool_pt argsepid; +bool_pt argbits32; +bool_pt argstripflag; +bool_pt arguzp; +{ + char buf4[4]; +#ifdef EDOS + char *commandname; +#endif + char *cptr; + struct nlist extsym; + flags_t flags; + struct modstruct *modptr; + char seg; + unsigned sizecount; + offset_t tempoffset; + struct symstruct *symptr; + + sepid = argsepid; + bits32 = argbits32; + stripflag = argstripflag; +#ifdef BSD_A_OUT + uzp = arguzp && !reloc_output; +#else + uzp = arguzp; +#endif + if (uzp) + { + if (btextoffset == 0) + btextoffset = page_size(); + if (bdataoffset == 0 && sepid) + bdataoffset = page_size(); + } +#ifdef EDOS + commandname = stralloc(outfilename); + if ((cptr = strchr(commandname, ':')) != NULL) + commandname = cptr + 1; + if ((cptr = strrchr(commandname, '.')) != NULL) + *cptr = 0; +#endif + + /* 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 */ + } +#ifdef EDOS + curseg = 0; /* data seg, s.b. variable */ +#else + curseg = 3; +#endif + symres("__edata"); + symres("__end"); + curseg = 0; /* text seg, s.b. variable */ + symres("__etext"); + + /* 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 != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++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) + { +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + undefined(symptr->name); + } + else + { +#ifdef BSD_A_OUT +#if 0 + if (!reloc_output) +#else + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif +#endif + { + tempoffset = ld_roundup(symptr->value, 4, offset_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)); +#ifndef EDOS + + /* adjust sizes to even to get quad boundaries */ + /* this should be specifiable dynamically */ + segsz[seg] = ld_roundup(segsz[seg], 4, offset_t); + comsz[seg] = ld_roundup(comsz[seg], 4, offset_t); +#endif + cptr += sizecount; + } + } + + /* calculate seg positions now their sizes are known */ + /* temp use fixed order 0D 0C 1D 1C 2D 2C ... */ + /* assume seg 0 is text and rest are data */ +#ifdef EDOS + if (btextoffset == 0) + btextoffset = binheaderlength(commandname); +#endif + segpos[0] = segbase[0] = spos = btextoffset; + combase[0] = segbase[0] + segsz[0]; + segadj[1] = segadj[0] = -btextoffset; + etextpadoff = etextoffset = combase[0] + comsz[0]; + if (sepid) + { + etextpadoff = ld_roundup(etextoffset, 0x10, offset_t); + segadj[1] += etextpadoff - bdataoffset; + } + else if (bdataoffset == 0) + bdataoffset = etextpadoff; + segpos[1] = segbase[1] = edataoffset = bdataoffset; + combase[1] = segbase[1] + segsz[1]; + for (seg = 2; seg < NSEG; ++seg) + { + segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1]; + 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]) & ~0xFF) != 0) + segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF) & ~0xFF; + } + combase[seg] = segbase[seg] + segsz[seg]; + segadj[seg] = segadj[seg - 1]; + } + + /* relocate symbols by offsets of segments in memory */ + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) + { + if (symptr->flags & (C_MASK | SA_MASK)) + { +#ifdef BSD_A_OUT +#if 0 + if (!reloc_output) +#else + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif +#endif + symptr->value += combase[symptr->flags & SEGM_MASK]; + } + else +#ifdef BSD_A_OUT + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif + symptr->value += segbase[symptr->flags & SEGM_MASK]; + } + } + + /* adjust special symbols */ + for (seg = 0; seg < NSEG; ++seg) + { + if (segsz[seg] != 0) + /* only count data of nonzero length */ + 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 */ + } + setsym("__etext", etextoffset); + setsym("__edata", edataoffset); + setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]); + + openout(outfilename); +#ifdef BSD_A_OUT + if (reloc_output) + seektrel(FILEHEADERLENGTH + + (long) (etextpadoff - btextoffset) + + (long) (edataoffset - bdataoffset)); +#endif +#ifdef EDOS + writeheader(commandname); +#else + writeheader(); +#endif + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + linkmod(modptr); + padmod(modptr); + } + + /* dump symbol table */ +#ifdef MINIX + if (!stripflag) + { +#ifdef BSD_A_OUT + unsigned stringoff; +#endif + + seekout(FILEHEADERLENGTH + + (long) (etextpadoff - btextoffset) + + (long) (edataoffset - bdataoffset) +#ifdef BSD_A_OUT + + ((long) ndreloc + ntreloc) + * (long) sizeof(struct relocation_info) +#endif + ); + extsym.n_was_numaux = extsym.n_was_type = 0; +#ifdef BSD_A_OUT + stringoff = 4; +#endif + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr) + { +#ifdef BSD_A_OUT + offtocn((char *) &extsym.n_was_strx, + (offset_t) stringoff, 4); +#else + strncpy((char *) &extsym.n_was_name, symptr->name, + sizeof extsym.n_was_name); +#endif + u4cn((char *) &extsym.n_value, (u4_t) symptr->value, + sizeof extsym.n_value); + if ((flags = symptr->flags) & A_MASK) + extsym.n_was_sclass = N_ABS; + else if (flags & (E_MASK | I_MASK)) + extsym.n_was_sclass = C_EXT; + else + extsym.n_was_sclass = C_STAT; + if (!(flags & I_MASK) || +#ifdef BSD_A_OUT + !reloc_output && +#endif + flags & C_MASK) + switch (flags & (A_MASK | SEGM_MASK)) + { + case 0: + extsym.n_was_sclass |= N_TEXT; + case A_MASK: + break; + default: + if (flags & (C_MASK | SA_MASK)) + extsym.n_was_sclass |= N_BSS; + else + extsym.n_was_sclass |= N_DATA; + break; + } + writeout((char *) &extsym, sizeof extsym); + ++nsym; +#ifdef BSD_A_OUT + stringoff += strlen(symptr->name) + 1; +#endif + } + } +#ifdef BSD_A_OUT + offtocn((char *) &extsym.n_was_strx, (offset_t) stringoff, 4); + writeout((char *) &extsym.n_was_strx, 4); + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr) + writeout(symptr->name, strlen(symptr->name) + 1); + } +#endif + seekout((long) offsetof(struct exec, a_syms)); + u4cn(buf4, (u4_t) nsym * sizeof extsym, + memsizeof(struct exec, a_syms)); + writeout(buf4, memsizeof(struct exec, a_syms)); +#if defined (BSD_A_OUT) && !defined(__linux__) + seekout((long) offsetof(struct exec, a_trsize)); + u4cn(buf4, (u4_t) ntreloc * sizeof(struct relocation_info), + memsizeof(struct exec, a_trsize)); + writeout(buf4, memsizeof(struct exec, a_trsize)); + seekout((long) offsetof(struct exec, a_drsize)); + u4cn(buf4, (u4_t) ndreloc * sizeof(struct relocation_info), + memsizeof(struct exec, a_drsize)); + writeout(buf4, memsizeof(struct exec, a_drsize)); +#endif + } +#endif /* MINIX */ + closeout(); +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + executable(); +} + +#ifdef EDOS + +PRIVATE unsigned binheaderlength(commandname) +char *commandname; +{ + unsigned count; + char *name; + struct entrylist *elptr; + struct symstruct *startptr; + + count = 2 + 2 + 1; /* len len nul */ + startptr = findsym("start"); + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + { + name = idconvert(elptr, commandname); + count += strlen(name) + 1 + 2 + 1; /* nul off flg */ + ourfree(name); + if (startptr != NULL) + count += 6; /* LBSR $xxxx and LBRA $xxxx */ + } + return count; +} + +/* convert name of symbol (entry) list element to a Basic identifier */ +/* new name is built in storage obtained from stralloc() */ +/* the special name _main is converted to the command name first */ +/* copy upper case and numerals, convert lower case to upper, ignore rest */ + +PRIVATE char *idconvert(elptr, commandname) +struct entrylist *elptr; +char *commandname; +{ + char *name; + char *newname; + + if (strcmp(name = elptr->elsymptr->name, "_main") == 0) + name = commandname; + newname = stralloc(name); + { + register char *t; + register char *s; + + t = newname; + s = name; + do + { + if (*s >= '0' && *s <= '9' || *s >= 'A' && *s <= 'Z') + *t++ = *s; + if (*s >= 'a' && *s <= 'z') + *t++ = *s + ('A' - 'a'); + } + while (*s++); + *t = 0; + } + if (*newname < 'A') /* numeral or null */ + fatalerror("bad entry name"); + return newname; +} + +#endif /* EDOS */ + +PRIVATE void linkmod(modptr) +struct modstruct *modptr; +{ + char buf[ABS_TEXT_MAX]; + int command; + unsigned char modify; + offset_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((long) 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((unsigned) 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) + offset -= (spos + relocsize); + offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize); + writeout(buf, relocsize); +#ifdef BSD_A_OUT + if (reloc_output) + { + u4_t bitfield; + + if (curseg == 0) + { + ++ntreloc; + offtocn(buf, spos, 4); + writetrel(buf, 4); + } + else + { + ++ndreloc; + offtocn(buf, spos - segbase[1], 4); + writedrel(buf, 4); + } + if ((modify & SEGM_MASK) == 0) + bitfield = N_TEXT; + else + bitfield = N_DATA; + if (modify & R_MASK) + bitfield |= 1L << 24; + if (relocsize == 2) + bitfield |= 1L << 25; + else if (relocsize == 4) + bitfield |= 1L << 26; + u4cn(buf, bitfield, 4); + if (curseg == 0) + writetrel(buf, 4); + else + writedrel(buf, 4); + } +#endif /* BSD_A_OUT */ + 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) + offset -= (spos + relocsize); +#ifdef BSD_A_OUT + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif + offset += symptr->value; + offtocn(buf, offset, relocsize); + writeout(buf, relocsize); +#ifdef BSD_A_OUT + if (reloc_output) + { + u4_t bitfield; + + if (curseg == 0) + { + ++ntreloc; + offtocn(buf, spos, 4); + writetrel(buf, 4); + } + else + { + ++ndreloc; + offtocn(buf, spos - segbase[1], 4); + writedrel(buf, 4); + } + if (symptr->flags & I_MASK) + bitfield = (1L << 27) | symbolnum; + else if ((symptr->flags & SEGM_MASK) == 0) + bitfield = N_TEXT; + else if (symptr->flags & (C_MASK | SA_MASK)) + bitfield = N_BSS; + else + bitfield = N_DATA; + if (modify & R_MASK) + bitfield |= 1L << 24; + if (relocsize == 2) + bitfield |= 1L << 25; + else if (relocsize == 4) + bitfield |= 1L << 26; + u4cn(buf, bitfield, 4); + if (curseg == 0) + writetrel(buf, 4); + else + writedrel(buf, 4); + } +#endif /* BSD_A_OUT */ + spos += relocsize; + } + } +} + +PRIVATE void linkrefs(modptr) +struct modstruct *modptr; +{ + register struct symstruct **symparray; + register struct symstruct *symptr; + + modptr->loadflag = TRUE; + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr->loadflag == FALSE) + linkrefs(symptr->modptr); +} + +PRIVATE void padmod(modptr) +struct modstruct *modptr; +{ + offset_t count; + char seg; + offset_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, offset_t) - segpos[seg]) != 0) + { + setseg(seg); + writenulls(size); + segpos[seg] = spos; + } + segbase[seg] = segpos[seg]; + } +} + +PRIVATE void setsym(name, value) +char *name; +offset_t value; +{ + struct symstruct *symptr; + +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + if ((symptr = findsym(name)) != NULL) + symptr->value = value; +} + +PRIVATE void symres(name) +register char *name; +{ + register struct symstruct *symptr; + + if ((symptr = findsym(name)) != NULL) + { + if ((symptr->flags & SEGM_MASK) == SEGM_MASK) + symptr->flags &= ~SEGM_MASK | curseg; + if (symptr->flags != (I_MASK | curseg) || symptr->value != 0) + reserved(name); +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + symptr->flags = E_MASK | curseg; /* show defined, not common */ + } +} + +/* set new segment */ + +PRIVATE void setseg(newseg) +unsigned newseg; +{ + if (newseg != curseg) + { + segpos[curseg] = spos; + spos = segpos[curseg = newseg]; + seekout(FILEHEADERLENGTH + (long) spos + (long) segadj[curseg]); + } +} + +PRIVATE void skip(countsize) +unsigned countsize; +{ + writenulls((offset_t) readsize(countsize)); +} + +#ifdef EDOS + +PRIVATE void writeheader(commandname) +char *commandname; +{ + char buf[MAX_OFFSET_SIZE]; + offset_t offset; + unsigned headlength; + char *name; + struct entrylist *elptr; + struct symstruct *startptr; + + headlength = binheaderlength(commandname); + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + headlength -= 6; + offset = headlength; + startptr = findsym("start"); + offtocn(buf, edataoffset, 2); + writeout(buf, 2); + writechar(0xFF); /* dummy data length 0xFFFF takes everything */ + writechar(0xFF); + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + { + name = idconvert(elptr, commandname); + writeout(name, (unsigned) strlen(name) + 1); + ourfree(name); + offtocn(buf, startptr == NULL ? elptr->elsymptr->value : offset, 2); + writeout(buf, 2); + writechar(0x82); /* 8 = set flags from here, 2 = cmd line */ + offset += 6; /* LBSR $xxxx and LBRA $xxxx */ + } + writechar(0); + if (startptr != NULL) + { + offset = headlength + 3; /* over 1st LBSR */ + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + { + writechar(0x17); /* LBSR */ + offtocn(buf, startptr->value - offset, 2); + writeout(buf, 2); + writechar(0x16); /* LBRA */ + offtocn(buf, elptr->elsymptr->value - offset - 3, 2); + writeout(buf, 2); + offset += 6; + } + } +} + +#endif /* EDOS */ + +#ifdef MINIX + +PRIVATE void writeheader() +{ + struct exec header; + + memset(&header, 0, sizeof header); + header.a_magic[0] = A_MAGIC0; + header.a_magic[1] = A_MAGIC1; +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + { + header.a_flags = sepid ? A_SEP : A_EXEC; + if (uzp) + header.a_flags |= A_UZP; + } +#ifdef BSD_A_OUT + header.a_cpu = (bits32 || reloc_output) ? A_I80386 : A_I8086; +#else + header.a_cpu = bits32 ? A_I80386 : A_I8086; +#endif + header.a_hdrlen = FILEHEADERLENGTH; + offtocn((char *) &header.a_text, etextpadoff - btextoffset, + sizeof header.a_text); + offtocn((char *) &header.a_data, edataoffset - bdataoffset, + sizeof header.a_data); + offtocn((char *) &header.a_bss, endoffset - edataoffset, + sizeof header.a_bss); +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + { + if (uzp) + offtocn((char *) &header.a_entry, page_size(), + sizeof header.a_entry); + offtocn((char *) &header.a_total, (offset_t) + (endoffset < 0x00010000L ? 0x00010000L : endoffset + 0x0008000L), + sizeof header.a_total); + } + writeout((char *) &header, FILEHEADERLENGTH); +} + +#endif /* MINIX */ + +PRIVATE void writenulls(count) +offset_t count; +{ + spos += count; + while (count--) + writechar(0); +} |