📄 outieee.c
字号:
/* outieee.c output routines for the Netwide Assembler to produce * IEEE-std object files * * The Netwide Assembler is copyright (C) 1996 Simon Tatham and * Julian Hall. All rights reserved. The software is * redistributable under the licence given in the file "Licence" * distributed in the NASM archive. *//* notes: I have tried to make this correspond to the IEEE version * of the standard, specifically the primary ASCII version. It should * be trivial to create the binary version given this source (which is * one of MANY things that have to be done to make this correspond to * the hp-microtek version of the standard). * * 16-bit support is assumed to use 24-bit addresses * The linker can sort out segmentation-specific stuff * if it keeps track of externals * in terms of being relative to section bases * * A non-standard variable type, the 'Yn' variable, has been introduced. * Basically it is a reference to extern 'n'- denoting the low limit * (L-variable) of the section that extern 'n' is defined in. Like the * x variable, there may be no explicit assignment to it, it is derived * from the public definition corresponding to the extern name. This * is required because the one thing the mufom guys forgot to do well was * take into account segmented architectures. * * I use comment classes for various things and these are undefined by * the standard. * * Debug info should be considered totally non-standard (local labels are * standard but linenum records are not covered by the standard. * Type defs have the standard format but absolute meanings for ordinal * types are not covered by the standard.) * * David Lindauer, LADsoft */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <stdarg.h> /* Note: we need the ANSI version of stdarg.h */#include <ctype.h>#include "nasm.h"#include "nasmlib.h"#include "outform.h"#ifdef OF_IEEE#define ARRAY_BOT 0x1static char ieee_infile[FILENAME_MAX];static int ieee_uppercase;static efunc error;static ldfunc deflabel;static FILE *ofp;static int any_segs;static int arrindex;#define HUNKSIZE 1024 /* Size of the data hunk */#define EXT_BLKSIZ 512#define LDPERLINE 32 /* bytes per line in output */struct ieeeSection;struct LineNumber { struct LineNumber *next; struct ieeeSection *segment; long offset; long lineno;};static struct FileName { struct FileName *next; char *name; long index;} *fnhead, **fntail;static struct Array { struct Array *next; unsigned size; int basetype;} *arrhead, **arrtail;static struct ieeePublic { struct ieeePublic *next; char *name; long offset; long segment; /* only if it's far-absolute */ long index; int type; /* for debug purposes */ } *fpubhead, **fpubtail, *last_defined;static struct ieeeExternal { struct ieeeExternal *next; char *name; long commonsize;} *exthead, **exttail;static int externals;static struct ExtBack { struct ExtBack *next; int index[EXT_BLKSIZ];} *ebhead, **ebtail;/* NOTE: the first segment MUST be the lineno segment */static struct ieeeSection { struct ieeeObjData *data,*datacurr; struct ieeeSection *next; struct ieeeFixupp *fptr, * flptr; long index; /* the NASM segment id */ long ieee_index; /* the OBJ-file segment index */ long currentpos; long align; /* can be SEG_ABS + absolute addr */ long startpos; enum { CMB_PRIVATE = 0, CMB_PUBLIC = 2, CMB_COMMON = 6 } combine; long use32; /* is this segment 32-bit? */ struct ieeePublic *pubhead, **pubtail, *lochead, **loctail; char *name;} *seghead, **segtail, *ieee_seg_needs_update;struct ieeeObjData { struct ieeeObjData *next; unsigned char data[HUNKSIZE];};struct ieeeFixupp { struct ieeeFixupp *next; enum { FT_SEG = 0, FT_REL = 1, FT_OFS = 2, FT_EXT = 3, FT_WRT = 4, FT_EXTREL = 5, FT_EXTWRT = 6, FT_EXTSEG = 7 } ftype; short size; long id1; long id2; long offset; long addend;}; static long ieee_entry_seg, ieee_entry_ofs;static int checksum;extern struct ofmt of_ieee;static void ieee_data_new(struct ieeeSection *);static void ieee_write_fixup (long, long, struct ieeeSection *, int, unsigned long, long);static void ieee_install_fixup(struct ieeeSection *, struct ieeeFixupp *);static long ieee_segment (char *, int, int *);static void ieee_write_file(int debuginfo);static void ieee_write_byte(struct ieeeSection *, int);static void ieee_write_word(struct ieeeSection *, int);static void ieee_write_dword(struct ieeeSection *, long);static void ieee_putascii(char *, ...);static void ieee_putcs(int);static long ieee_putld(long, long, unsigned char *);static long ieee_putlr(struct ieeeFixupp *);static void ieee_unqualified_name(char *, char *);/* * pup init */static void ieee_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) { (void) eval; ofp = fp; error = errfunc; deflabel = ldef; any_segs = FALSE; fpubhead = NULL; fpubtail = &fpubhead; exthead = NULL; exttail = &exthead; externals = 1; ebhead = NULL; ebtail = &ebhead; seghead = ieee_seg_needs_update = NULL; segtail = &seghead; ieee_entry_seg = NO_SEG; ieee_uppercase = FALSE; checksum = 0; of_ieee.current_dfmt->init (&of_ieee,NULL,fp,errfunc);}static int ieee_set_info(enum geninfo type, char **val){ (void) type; (void) val; return 0;}/* * Rundown */static void ieee_cleanup (int debuginfo) { ieee_write_file(debuginfo); of_ieee.current_dfmt->cleanup (); fclose (ofp); while (seghead) { struct ieeeSection *segtmp = seghead; seghead = seghead->next; while (segtmp->pubhead) { struct ieeePublic *pubtmp = segtmp->pubhead; segtmp->pubhead = pubtmp->next; nasm_free (pubtmp); } while (segtmp->fptr) { struct ieeeFixupp *fixtmp = segtmp->fptr; segtmp->fptr = fixtmp->next; nasm_free(fixtmp); } while (segtmp->data) { struct ieeeObjData *dattmp = segtmp->data; segtmp->data = dattmp->next; nasm_free(dattmp); } nasm_free (segtmp); } while (fpubhead) { struct ieeePublic *pubtmp = fpubhead; fpubhead = fpubhead->next; nasm_free (pubtmp); } while (exthead) { struct ieeeExternal *exttmp = exthead; exthead = exthead->next; nasm_free (exttmp); } while (ebhead) { struct ExtBack *ebtmp = ebhead; ebhead = ebhead->next; nasm_free (ebtmp); }}/* * callback for labels */static void ieee_deflabel (char *name, long segment, long offset, int is_global, char *special) { /* * We have three cases: * * (i) `segment' is a segment-base. If so, set the name field * for the segment structure it refers to, and then * return. * * (ii) `segment' is one of our segments, or a SEG_ABS segment. * Save the label position for later output of a PUBDEF record. * * * (iii) `segment' is not one of our segments. Save the label * position for later output of an EXTDEF. */ struct ieeeExternal *ext; struct ExtBack *eb; struct ieeeSection *seg; int i; if (special) { error(ERR_NONFATAL, "unrecognised symbol type `%s'", special); } /* * First check for the double-period, signifying something * unusual. */ if (name[0] == '.' && name[1] == '.') { if (!strcmp(name, "..start")) { ieee_entry_seg = segment; ieee_entry_ofs = offset; } return; } /* * Case (i): */ if (ieee_seg_needs_update) { ieee_seg_needs_update->name = name; return; } if (segment < SEG_ABS && segment != NO_SEG && segment % 2) return; /* * case (ii) */ if (segment >= SEG_ABS) { /* * SEG_ABS subcase of (ii). */ if (is_global) { struct ieeePublic *pub; pub = *fpubtail = nasm_malloc(sizeof(*pub)); fpubtail = &pub->next; pub->next = NULL; pub->name = name; pub->offset = offset; pub->segment = segment & ~SEG_ABS; } return; } for (seg = seghead; seg && is_global; seg = seg->next) if (seg->index == segment) { struct ieeePublic *pub; last_defined = pub = *seg->pubtail = nasm_malloc(sizeof(*pub)); seg->pubtail = &pub->next; pub->next = NULL; pub->name = name; pub->offset = offset; pub->index = seg->ieee_index; pub->segment = -1; return; } /* * Case (iii). */ if (is_global) { ext = *exttail = nasm_malloc(sizeof(*ext)); ext->next = NULL; exttail = &ext->next; ext->name = name; if (is_global == 2) ext->commonsize = offset; else ext->commonsize = 0; i = segment/2; eb = ebhead; if (!eb) { eb = *ebtail = nasm_malloc(sizeof(*eb)); eb->next = NULL; ebtail = &eb->next; } while (i > EXT_BLKSIZ) { if (eb && eb->next) eb = eb->next; else { eb = *ebtail = nasm_malloc(sizeof(*eb)); eb->next = NULL; ebtail = &eb->next; } i -= EXT_BLKSIZ; } eb->index[i] = externals++; } }/* * Put data out */static void ieee_out (long segto, const void *data, unsigned long type, long segment, long wrt) { unsigned long size, realtype; const unsigned char *ucdata; long ldata; struct ieeeSection *seg; /* * handle absolute-assembly (structure definitions) */ if (segto == NO_SEG) { if ((type & OUT_TYPMASK) != OUT_RESERVE) error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]" " space"); return; } /* * If `any_segs' is still FALSE, we must define a default * segment. */ if (!any_segs) { int tempint; /* ignored */ if (segto != ieee_segment("__NASMDEFSEG", 2, &tempint)) error (ERR_PANIC, "strange segment conditions in IEEE driver"); } /* * Find the segment we are targetting. */ for (seg = seghead; seg; seg = seg->next) if (seg->index == segto) break; if (!seg) error (ERR_PANIC, "code directed to nonexistent segment?"); size = type & OUT_SIZMASK; realtype = type & OUT_TYPMASK; if (realtype == OUT_RAWDATA) { ucdata = data; while (size--) ieee_write_byte(seg,*ucdata++); } else if (realtype == OUT_ADDRESS || realtype == OUT_REL2ADR || realtype == OUT_REL4ADR) { if (segment == NO_SEG && realtype != OUT_ADDRESS) error(ERR_NONFATAL, "relative call to absolute address not" " supported by IEEE format"); ldata = *(long *)data; if (realtype == OUT_REL2ADR) ldata += (size-2); if (realtype == OUT_REL4ADR) ldata += (size-4); ieee_write_fixup (segment, wrt, seg, size, realtype,ldata); if (size == 2) ieee_write_word (seg, ldata); else ieee_write_dword (seg, ldata); } else if (realtype == OUT_RESERVE) { while (size--) ieee_write_byte(seg,0); }}static void ieee_data_new(struct ieeeSection *segto) { if (!segto->data) segto->data = segto->datacurr = nasm_malloc(sizeof(*(segto->datacurr))); else segto->datacurr = segto->datacurr->next = nasm_malloc(sizeof(*(segto->datacurr))); segto->datacurr->next = NULL;}/* * this routine is unalduterated bloatware. I usually don't do this * but I might as well see what it is like on a harmless program. * If anyone wants to optimize this is a good canditate! */static void ieee_write_fixup (long segment, long wrt, struct ieeeSection * segto, int size, unsigned long realtype, long offset) { struct ieeeSection *target; struct ieeeFixupp s; /* Don't put a fixup for things NASM can calculate */ if (wrt == NO_SEG && segment == NO_SEG) return; s.ftype = -1; /* if it is a WRT offset */ if (wrt != NO_SEG) { s.ftype = FT_WRT; s.addend = offset; if (wrt >= SEG_ABS) s.id1 = -(wrt-SEG_ABS); else { if (wrt %2 && realtype != OUT_REL2ADR && realtype != OUT_REL4ADR) { wrt--; for (target = seghead; target; target = target->next) if (target->index == wrt) break; if (target) { s.id1 = target->ieee_index; for (target = seghead; target; target = target->next) if (target->index == segment) break; if (target) s.id2 = target->ieee_index; else { /* * Now we assume the segment field is being used * to hold an extern index */ long i = segment/2; struct ExtBack *eb = ebhead; while (i > EXT_BLKSIZ) { if (eb)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -