NASM 0.98bf
[nasm.git] / outobj.c
blobbf4337724a2053bf95b906c88be5868e1910fbaf
1 /* outobj.c output routines for the Netwide Assembler to produce
2 * .OBJ object files
4 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
5 * Julian Hall. All rights reserved. The software is
6 * redistributable under the licence given in the file "Licence"
7 * distributed in the NASM archive.
8 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
15 #include "nasm.h"
16 #include "nasmlib.h"
17 #include "outform.h"
19 #ifdef OF_OBJ
22 * outobj.c is divided into two sections. The first section is low level
23 * routines for creating obj records; It has nearly zero NASM specific
24 * code. The second section is high level routines for processing calls and
25 * data structures from the rest of NASM into obj format.
27 * It should be easy (though not zero work) to lift the first section out for
28 * use as an obj file writer for some other assembler or compiler.
32 * These routines are built around the ObjRecord data struture. An ObjRecord
33 * holds an object file record that may be under construction or complete.
35 * A major function of these routines is to support continuation of an obj
36 * record into the next record when the maximum record size is exceeded. The
37 * high level code does not need to worry about where the record breaks occur.
38 * It does need to do some minor extra steps to make the automatic continuation
39 * work. Those steps may be skipped for records where the high level knows no
40 * continuation could be required.
42 * 1) An ObjRecord is allocated and cleared by obj_new, or an existing ObjRecord
43 * is cleared by obj_clear.
45 * 2) The caller should fill in .type.
47 * 3) If the record is continuable and there is processing that must be done at
48 * the start of each record then the caller should fill in .ori with the
49 * address of the record initializer routine.
51 * 4) If the record is continuable and it should be saved (rather than emitted
52 * immediately) as each record is done, the caller should set .up to be a
53 * pointer to a location in which the caller keeps the master pointer to the
54 * ObjRecord. When the record is continued, the obj_bump routine will then
55 * allocate a new ObjRecord structure and update the master pointer.
57 * 5) If the .ori field was used then the caller should fill in the .parm with
58 * any data required by the initializer.
60 * 6) The caller uses the routines: obj_byte, obj_word, obj_rword, obj_dword,
61 * obj_x, obj_index, obj_value and obj_name to fill in the various kinds of
62 * data required for this record.
64 * 7) If the record is continuable, the caller should call obj_commit at each
65 * point where breaking the record is permitted.
67 * 8) To write out the record, the caller should call obj_emit2. If the
68 * caller has called obj_commit for all data written then he can get slightly
69 * faster code by calling obj_emit instead of obj_emit2.
71 * Most of these routines return an ObjRecord pointer. This will be the input
72 * pointer most of the time and will be the new location if the ObjRecord
73 * moved as a result of the call. The caller may ignore the return value in
74 * three cases: It is a "Never Reallocates" routine; or The caller knows
75 * continuation is not possible; or The caller uses the master pointer for the
76 * next operation.
79 #define RECORD_MAX 1024 /* maximum size of _any_ record */
80 #define OBJ_PARMS 3 /* maximum .parm used by any .ori routine */
82 #define FIX_08_LOW 0x8000 /* location type for various fixup subrecords */
83 #define FIX_16_OFFSET 0x8400
84 #define FIX_16_SELECTOR 0x8800
85 #define FIX_32_POINTER 0x8C00
86 #define FIX_08_HIGH 0x9000
87 #define FIX_32_OFFSET 0xA400
88 #define FIX_48_POINTER 0xAC00
90 enum RecordID { /* record ID codes */
92 THEADR = 0x80, /* module header */
93 COMENT = 0x88, /* comment record */
95 LINNUM = 0x94, /* line number record */
96 LNAMES = 0x96, /* list of names */
98 SEGDEF = 0x98, /* segment definition */
99 GRPDEF = 0x9A, /* group definition */
100 EXTDEF = 0x8C, /* external definition */
101 PUBDEF = 0x90, /* public definition */
102 COMDEF = 0xB0, /* common definition */
104 LEDATA = 0xA0, /* logical enumerated data */
105 FIXUPP = 0x9C, /* fixups (relocations) */
107 MODEND = 0x8A /* module end */
110 enum ComentID { /* ID codes for comment records */
112 dEXTENDED = 0xA1, /* tells that we are using translator-specific extensions */
113 dLINKPASS = 0xA2, /* link pass 2 marker */
114 dTYPEDEF = 0xE3, /* define a type */
115 dSYM = 0xE6, /* symbol debug record */
116 dFILNAME = 0xE8, /* file name record */
117 dCOMPDEF = 0xEA /* compiler type info */
121 typedef struct ObjRecord ObjRecord;
122 typedef void ORI(ObjRecord *orp);
124 struct ObjRecord {
125 ORI *ori; /* Initialization routine */
126 int used; /* Current data size */
127 int committed; /* Data size at last boundary */
128 int x_size; /* (see obj_x) */
129 unsigned int type; /* Record type */
130 ObjRecord *child; /* Associated record below this one */
131 ObjRecord **up; /* Master pointer to this ObjRecord */
132 ObjRecord *back; /* Previous part of this record */
133 unsigned long parm[OBJ_PARMS]; /* Parameters for ori routine */
134 unsigned char buf[RECORD_MAX];
137 static void obj_fwrite(ObjRecord *orp);
138 static void ori_ledata(ObjRecord *orp);
139 static void ori_pubdef(ObjRecord *orp);
140 static void ori_null(ObjRecord *orp);
141 static ObjRecord *obj_commit(ObjRecord *orp);
142 static void obj_write_fixup (ObjRecord *orp, int bytes,
143 int segrel, long seg, long wrt);
145 static int obj_uppercase; /* Flag: all names in uppercase */
148 * Clear an ObjRecord structure. (Never reallocates).
149 * To simplify reuse of ObjRecord's, .type, .ori and .parm are not cleared.
151 static ObjRecord *obj_clear(ObjRecord *orp)
153 orp->used = 0;
154 orp->committed = 0;
155 orp->x_size = 0;
156 orp->child = NULL;
157 orp->up = NULL;
158 orp->back = NULL;
159 return (orp);
163 * Emit an ObjRecord structure. (Never reallocates).
164 * The record is written out preceeded (recursively) by its previous part (if
165 * any) and followed (recursively) by its child (if any).
166 * The previous part and the child are freed. The main ObjRecord is cleared,
167 * not freed.
169 static ObjRecord *obj_emit(ObjRecord *orp)
171 if (orp->back) {
172 obj_emit(orp->back);
173 nasm_free(orp->back);
176 if (orp->committed)
177 obj_fwrite(orp);
179 if (orp->child) {
180 obj_emit(orp->child);
181 nasm_free(orp->child);
184 return (obj_clear(orp));
188 * Commit and Emit a record. (Never reallocates).
190 static ObjRecord *obj_emit2(ObjRecord *orp)
192 obj_commit(orp);
193 return (obj_emit(orp));
197 * Allocate and clear a new ObjRecord; Also sets .ori to ori_null
199 static ObjRecord *obj_new(void)
201 ObjRecord *orp;
203 orp = obj_clear( nasm_malloc(sizeof(ObjRecord)) );
204 orp->ori = ori_null;
205 return (orp);
209 * Advance to the next record because the existing one is full or its x_size
210 * is incompatible.
211 * Any uncommited data is moved into the next record.
213 static ObjRecord *obj_bump(ObjRecord *orp)
215 ObjRecord *nxt;
216 int used = orp->used;
217 int committed = orp->committed;
219 if (orp->up) {
220 *orp->up = nxt = obj_new();
221 nxt->ori = orp->ori;
222 nxt->type = orp->type;
223 nxt->up = orp->up;
224 nxt->back = orp;
225 memcpy( nxt->parm, orp->parm, sizeof(orp->parm));
226 } else
227 nxt = obj_emit(orp);
229 used -= committed;
230 if (used) {
231 nxt->committed = 1;
232 nxt->ori (nxt);
233 nxt->committed = nxt->used;
234 memcpy( nxt->buf + nxt->committed, orp->buf + committed, used);
235 nxt->used = nxt->committed + used;
238 return (nxt);
242 * Advance to the next record if necessary to allow the next field to fit.
244 static ObjRecord *obj_check(ObjRecord *orp, int size)
246 if (orp->used + size > RECORD_MAX)
247 orp = obj_bump(orp);
249 if (!orp->committed) {
250 orp->committed = 1;
251 orp->ori (orp);
252 orp->committed = orp->used;
255 return (orp);
259 * All data written so far is commited to the current record (won't be moved to
260 * the next record in case of continuation).
262 static ObjRecord *obj_commit(ObjRecord *orp)
264 orp->committed = orp->used;
265 return (orp);
269 * Write a byte
271 static ObjRecord *obj_byte(ObjRecord *orp, unsigned char val)
273 orp = obj_check(orp, 1);
274 orp->buf[orp->used] = val;
275 orp->used++;
276 return (orp);
280 * Write a word
282 static ObjRecord *obj_word(ObjRecord *orp, unsigned int val)
284 orp = obj_check(orp, 2);
285 orp->buf[orp->used] = (unsigned char)(val & 0xFF);
286 orp->buf[orp->used+1] = (unsigned char)((val >> 8) & 0xFF);
287 orp->used += 2;
288 return (orp);
292 * Write a reversed word
294 static ObjRecord *obj_rword(ObjRecord *orp, unsigned int val)
296 orp = obj_check(orp, 2);
297 orp->buf[orp->used] = (unsigned char)((val >> 8) & 0xFF);
298 orp->buf[orp->used+1] = (unsigned char)(val & 0xFF);
299 orp->used += 2;
300 return (orp);
304 * Write a dword
306 static ObjRecord *obj_dword(ObjRecord *orp, unsigned long val)
308 orp = obj_check(orp, 4);
309 orp->buf[orp->used] = (unsigned char)(val & 0xFF);
310 orp->buf[orp->used+1] = (unsigned char)((val >> 8) & 0xFF);
311 orp->buf[orp->used+2] = (unsigned char)((val >> 16) & 0xFF);
312 orp->buf[orp->used+3] = (unsigned char)((val >> 24) & 0xFF);
313 orp->used += 4;
314 return (orp);
318 * All fields of "size x" in one obj record must be the same size (either 16
319 * bits or 32 bits). There is a one bit flag in each record which specifies
320 * which.
321 * This routine is used to force the current record to have the desired
322 * x_size. x_size is normally automatic (using obj_x), so that this
323 * routine should be used outside obj_x, only to provide compatibility with
324 * linkers that have bugs in their processing of the size bit.
327 static ObjRecord *obj_force(ObjRecord *orp, int x)
329 if (orp->x_size == (x^48))
330 orp = obj_bump(orp);
331 orp->x_size = x;
332 return (orp);
336 * This routine writes a field of size x. The caller does not need to worry at
337 * all about whether 16-bits or 32-bits are required.
339 static ObjRecord *obj_x(ObjRecord *orp, unsigned long val)
341 if (orp->type & 1)
342 orp->x_size = 32;
343 if (val > 0xFFFF)
344 orp = obj_force(orp, 32);
345 if (orp->x_size == 32)
346 return (obj_dword(orp, val));
347 orp->x_size = 16;
348 return (obj_word(orp, val));
352 * Writes an index
354 static ObjRecord *obj_index(ObjRecord *orp, unsigned int val)
356 if (val < 128)
357 return ( obj_byte(orp, val) );
358 return (obj_word(orp, (val>>8) | (val<<8) | 0x80));
362 * Writes a variable length value
364 static ObjRecord *obj_value(ObjRecord *orp, unsigned long val)
366 if (val <= 128)
367 return ( obj_byte(orp, (unsigned char)val) );
368 if (val <= 0xFFFF) {
369 orp = obj_byte(orp, 129);
370 return ( obj_word(orp, val) );
372 if (val <= 0xFFFFFF)
373 return ( obj_dword(orp, (val<<8) + 132 ) );
374 orp = obj_byte(orp, 136);
375 return ( obj_dword(orp, val) );
379 * Writes a counted string
381 static ObjRecord *obj_name(ObjRecord *orp, char *name)
383 int len = strlen(name);
384 unsigned char *ptr;
386 orp = obj_check(orp, len+1);
387 ptr = orp->buf + orp->used;
388 *ptr++ = len;
389 orp->used += len+1;
390 if (obj_uppercase)
391 while (--len >= 0) {
392 *ptr++ = toupper(*name);
393 name++;
394 } else
395 memcpy(ptr, name, len);
396 return (orp);
400 * Initializer for an LEDATA record.
401 * parm[0] = offset
402 * parm[1] = segment index
403 * During the use of a LEDATA ObjRecord, parm[0] is constantly updated to
404 * represent the offset that would be required if the record were split at the
405 * last commit point.
406 * parm[2] is a copy of parm[0] as it was when the current record was initted.
408 static void ori_ledata(ObjRecord *orp)
410 obj_index (orp, orp->parm[1]);
411 orp->parm[2] = orp->parm[0];
412 obj_x (orp, orp->parm[0]);
416 * Initializer for a PUBDEF record.
417 * parm[0] = group index
418 * parm[1] = segment index
419 * parm[2] = frame (only used when both indexes are zero)
421 static void ori_pubdef(ObjRecord *orp)
423 obj_index (orp, orp->parm[0]);
424 obj_index (orp, orp->parm[1]);
425 if ( !(orp->parm[0] | orp->parm[1]) )
426 obj_word (orp, orp->parm[2]);
430 * Initializer for a LINNUM record.
431 * parm[0] = group index
432 * parm[1] = segment index
434 static void ori_linnum(ObjRecord *orp)
436 obj_index (orp, orp->parm[0]);
437 obj_index (orp, orp->parm[1]);
440 * Initializer for a local vars record.
442 static void ori_local(ObjRecord *orp)
444 obj_byte (orp, 0x40);
445 obj_byte (orp, dSYM);
449 * Null initializer for records that continue without any header info
451 static void ori_null(ObjRecord *orp)
453 (void) orp; /* Do nothing */
457 * This concludes the low level section of outobj.c
460 static char obj_infile[FILENAME_MAX];
462 static efunc error;
463 static evalfunc evaluate;
464 static ldfunc deflabel;
465 static FILE *ofp;
466 static long first_seg;
467 static int any_segs;
468 static int passtwo;
469 static int arrindex;
471 #define GROUP_MAX 256 /* we won't _realistically_ have more
472 * than this many segs in a group */
473 #define EXT_BLKSIZ 256 /* block size for externals list */
475 struct Segment; /* need to know these structs exist */
476 struct Group;
478 struct LineNumber {
479 struct LineNumber *next;
480 struct Segment *segment;
481 long offset;
482 long lineno;
485 static struct FileName {
486 struct FileName *next;
487 char *name;
488 struct LineNumber *lnhead, **lntail;
489 int index;
490 } *fnhead, **fntail;
492 static struct Array {
493 struct Array *next;
494 unsigned size;
495 int basetype;
496 } *arrhead, **arrtail;
498 #define ARRAYBOT 31 /* magic number for first array index */
501 static struct Public {
502 struct Public *next;
503 char *name;
504 long offset;
505 long segment; /* only if it's far-absolute */
506 int type; /* only for local debug syms */
507 } *fpubhead, **fpubtail, *last_defined;
509 static struct External {
510 struct External *next;
511 char *name;
512 long commonsize;
513 long commonelem; /* element size if FAR, else zero */
514 int index; /* OBJ-file external index */
515 enum {
516 DEFWRT_NONE, /* no unusual default-WRT */
517 DEFWRT_STRING, /* a string we don't yet understand */
518 DEFWRT_SEGMENT, /* a segment */
519 DEFWRT_GROUP /* a group */
520 } defwrt_type;
521 union {
522 char *string;
523 struct Segment *seg;
524 struct Group *grp;
525 } defwrt_ptr;
526 struct External *next_dws; /* next with DEFWRT_STRING */
527 } *exthead, **exttail, *dws;
529 static int externals;
531 static struct ExtBack {
532 struct ExtBack *next;
533 struct External *exts[EXT_BLKSIZ];
534 } *ebhead, **ebtail;
536 static struct Segment {
537 struct Segment *next;
538 long index; /* the NASM segment id */
539 long obj_index; /* the OBJ-file segment index */
540 struct Group *grp; /* the group it belongs to */
541 unsigned long currentpos;
542 long align; /* can be SEG_ABS + absolute addr */
543 enum {
544 CMB_PRIVATE = 0,
545 CMB_PUBLIC = 2,
546 CMB_STACK = 5,
547 CMB_COMMON = 6
548 } combine;
549 long use32; /* is this segment 32-bit? */
550 struct Public *pubhead, **pubtail, *lochead, **loctail;
551 char *name;
552 char *segclass, *overlay; /* `class' is a C++ keyword :-) */
553 ObjRecord *orp;
554 } *seghead, **segtail, *obj_seg_needs_update;
556 static struct Group {
557 struct Group *next;
558 char *name;
559 long index; /* NASM segment id */
560 long obj_index; /* OBJ-file group index */
561 long nentries; /* number of elements... */
562 long nindices; /* ...and number of index elts... */
563 union {
564 long index;
565 char *name;
566 } segs[GROUP_MAX]; /* ...in this */
567 } *grphead, **grptail, *obj_grp_needs_update;
569 static struct ImpDef {
570 struct ImpDef *next;
571 char *extname;
572 char *libname;
573 unsigned int impindex;
574 char *impname;
575 } *imphead, **imptail;
577 static struct ExpDef {
578 struct ExpDef *next;
579 char *intname;
580 char *extname;
581 unsigned int ordinal;
582 int flags;
583 } *exphead, **exptail;
585 #define EXPDEF_FLAG_ORDINAL 0x80
586 #define EXPDEF_FLAG_RESIDENT 0x40
587 #define EXPDEF_FLAG_NODATA 0x20
588 #define EXPDEF_MASK_PARMCNT 0x1F
590 static long obj_entry_seg, obj_entry_ofs;
592 struct ofmt of_obj;
594 static long obj_segment (char *, int, int *);
595 static void obj_write_file(int debuginfo);
596 static int obj_directive (char *, char *, int);
598 static void obj_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
600 ofp = fp;
601 error = errfunc;
602 evaluate = eval;
603 deflabel = ldef;
604 first_seg = seg_alloc();
605 any_segs = FALSE;
606 fpubhead = NULL;
607 fpubtail = &fpubhead;
608 exthead = NULL;
609 exttail = &exthead;
610 imphead = NULL;
611 imptail = &imphead;
612 exphead = NULL;
613 exptail = &exphead;
614 dws = NULL;
615 externals = 0;
616 ebhead = NULL;
617 ebtail = &ebhead;
618 seghead = obj_seg_needs_update = NULL;
619 segtail = &seghead;
620 grphead = obj_grp_needs_update = NULL;
621 grptail = &grphead;
622 obj_entry_seg = NO_SEG;
623 obj_uppercase = FALSE;
624 passtwo = 0;
626 of_obj.current_dfmt->init (&of_obj,NULL,fp,errfunc);
629 static int obj_set_info(enum geninfo type, char **val)
631 (void) type;
632 (void) val;
634 return 0;
636 static void obj_cleanup (int debuginfo)
638 obj_write_file(debuginfo);
639 of_obj.current_dfmt->cleanup();
640 fclose (ofp);
641 while (seghead) {
642 struct Segment *segtmp = seghead;
643 seghead = seghead->next;
644 while (segtmp->pubhead) {
645 struct Public *pubtmp = segtmp->pubhead;
646 segtmp->pubhead = pubtmp->next;
647 nasm_free (pubtmp->name);
648 nasm_free (pubtmp);
650 nasm_free (segtmp->segclass);
651 nasm_free (segtmp->overlay);
652 nasm_free (segtmp);
654 while (fpubhead) {
655 struct Public *pubtmp = fpubhead;
656 fpubhead = fpubhead->next;
657 nasm_free (pubtmp->name);
658 nasm_free (pubtmp);
660 while (exthead) {
661 struct External *exttmp = exthead;
662 exthead = exthead->next;
663 nasm_free (exttmp);
665 while (imphead) {
666 struct ImpDef *imptmp = imphead;
667 imphead = imphead->next;
668 nasm_free (imptmp->extname);
669 nasm_free (imptmp->libname);
670 nasm_free (imptmp->impname); /* nasm_free won't mind if it's NULL */
671 nasm_free (imptmp);
673 while (exphead) {
674 struct ExpDef *exptmp = exphead;
675 exphead = exphead->next;
676 nasm_free (exptmp->extname);
677 nasm_free (exptmp->intname);
678 nasm_free (exptmp);
680 while (ebhead) {
681 struct ExtBack *ebtmp = ebhead;
682 ebhead = ebhead->next;
683 nasm_free (ebtmp);
685 while (grphead) {
686 struct Group *grptmp = grphead;
687 grphead = grphead->next;
688 nasm_free (grptmp);
692 static void obj_ext_set_defwrt (struct External *ext, char *id)
694 struct Segment *seg;
695 struct Group *grp;
697 for (seg = seghead; seg; seg = seg->next)
698 if (!strcmp(seg->name, id)) {
699 ext->defwrt_type = DEFWRT_SEGMENT;
700 ext->defwrt_ptr.seg = seg;
701 nasm_free (id);
702 return;
705 for (grp = grphead; grp; grp = grp->next)
706 if (!strcmp(grp->name, id)) {
707 ext->defwrt_type = DEFWRT_GROUP;
708 ext->defwrt_ptr.grp = grp;
709 nasm_free (id);
710 return;
713 ext->defwrt_type = DEFWRT_STRING;
714 ext->defwrt_ptr.string = id;
715 ext->next_dws = dws;
716 dws = ext;
719 static void obj_deflabel (char *name, long segment,
720 long offset, int is_global, char *special)
723 * We have three cases:
725 * (i) `segment' is a segment-base. If so, set the name field
726 * for the segment or group structure it refers to, and then
727 * return.
729 * (ii) `segment' is one of our segments, or a SEG_ABS segment.
730 * Save the label position for later output of a PUBDEF record.
731 * (Or a MODPUB, if we work out how.)
733 * (iii) `segment' is not one of our segments. Save the label
734 * position for later output of an EXTDEF, and also store a
735 * back-reference so that we can map later references to this
736 * segment number to the external index.
738 struct External *ext;
739 struct ExtBack *eb;
740 struct Segment *seg;
741 int i;
742 int used_special = FALSE; /* have we used the special text? */
745 * If it's a special-retry from pass two, discard it.
747 if (is_global == 3)
748 return;
751 * First check for the double-period, signifying something
752 * unusual.
754 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
755 if (!strcmp(name, "..start")) {
756 obj_entry_seg = segment;
757 obj_entry_ofs = offset;
758 return;
760 error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
764 * Case (i):
766 if (obj_seg_needs_update) {
767 obj_seg_needs_update->name = name;
768 return;
769 } else if (obj_grp_needs_update) {
770 obj_grp_needs_update->name = name;
771 return;
773 if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
774 return;
776 if (segment >= SEG_ABS || segment == NO_SEG) {
778 * SEG_ABS subcase of (ii).
780 if (is_global) {
781 struct Public *pub;
783 pub = *fpubtail = nasm_malloc(sizeof(*pub));
784 fpubtail = &pub->next;
785 pub->next = NULL;
786 pub->name = nasm_strdup(name);
787 pub->offset = offset;
788 pub->segment = (segment == NO_SEG ? 0 : segment & ~SEG_ABS);
790 if (special)
791 error(ERR_NONFATAL, "OBJ supports no special symbol features"
792 " for this symbol type");
793 return;
797 * If `any_segs' is still FALSE, we might need to define a
798 * default segment, if they're trying to declare a label in
799 * `first_seg'.
801 if (!any_segs && segment == first_seg) {
802 int tempint; /* ignored */
803 if (segment != obj_segment("__NASMDEFSEG", 2, &tempint))
804 error (ERR_PANIC, "strange segment conditions in OBJ driver");
807 for (seg = seghead; seg && is_global; seg = seg->next)
808 if (seg->index == segment) {
809 struct Public *loc = nasm_malloc (sizeof(*loc));
811 * Case (ii). Maybe MODPUB someday?
813 *seg->pubtail = loc;
814 seg->pubtail = &loc->next;
815 loc->next = NULL;
816 loc->name = nasm_strdup(name);
817 loc->offset = offset;
819 if (special)
820 error(ERR_NONFATAL, "OBJ supports no special symbol features"
821 " for this symbol type");
822 return;
826 * Case (iii).
828 if (is_global) {
829 ext = *exttail = nasm_malloc(sizeof(*ext));
830 ext->next = NULL;
831 exttail = &ext->next;
832 ext->name = name;
833 ext->defwrt_type = DEFWRT_NONE;
834 if (is_global == 2) {
835 ext->commonsize = offset;
836 ext->commonelem = 1; /* default FAR */
837 } else
838 ext->commonsize = 0;
840 else
841 return;
844 * Now process the special text, if any, to find default-WRT
845 * specifications and common-variable element-size and near/far
846 * specifications.
848 while (special && *special) {
849 used_special = TRUE;
852 * We might have a default-WRT specification.
854 if (!nasm_strnicmp(special, "wrt", 3)) {
855 char *p;
856 int len;
857 special += 3;
858 special += strspn(special, " \t");
859 p = nasm_strndup(special, len = strcspn(special, ":"));
860 obj_ext_set_defwrt (ext, p);
861 special += len;
862 if (*special && *special != ':')
863 error(ERR_NONFATAL, "`:' expected in special symbol"
864 " text for `%s'", ext->name);
865 else if (*special == ':')
866 special++;
870 * The NEAR or FAR keywords specify nearness or
871 * farness. FAR gives default element size 1.
873 if (!nasm_strnicmp(special, "far", 3)) {
874 if (ext->commonsize)
875 ext->commonelem = 1;
876 else
877 error(ERR_NONFATAL, "`%s': `far' keyword may only be applied"
878 " to common variables\n", ext->name);
879 special += 3;
880 special += strspn(special, " \t");
881 } else if (!nasm_strnicmp(special, "near", 4)) {
882 if (ext->commonsize)
883 ext->commonelem = 0;
884 else
885 error(ERR_NONFATAL, "`%s': `far' keyword may only be applied"
886 " to common variables\n", ext->name);
887 special += 4;
888 special += strspn(special, " \t");
892 * If it's a common, and anything else remains on the line
893 * before a further colon, evaluate it as an expression and
894 * use that as the element size. Forward references aren't
895 * allowed.
897 if (*special == ':')
898 special++;
899 else if (*special) {
900 if (ext->commonsize) {
901 expr *e;
902 struct tokenval tokval;
904 stdscan_reset();
905 stdscan_bufptr = special;
906 tokval.t_type = TOKEN_INVALID;
907 e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
908 if (e) {
909 if (!is_simple(e))
910 error (ERR_NONFATAL, "cannot use relocatable"
911 " expression as common-variable element size");
912 else
913 ext->commonelem = reloc_value(e);
915 special = stdscan_bufptr;
916 } else {
917 error (ERR_NONFATAL, "`%s': element-size specifications only"
918 " apply to common variables", ext->name);
919 while (*special && *special != ':')
920 special++;
921 if (*special == ':')
922 special++;
927 i = segment/2;
928 eb = ebhead;
929 if (!eb) {
930 eb = *ebtail = nasm_malloc(sizeof(*eb));
931 eb->next = NULL;
932 ebtail = &eb->next;
934 while (i > EXT_BLKSIZ) {
935 if (eb && eb->next)
936 eb = eb->next;
937 else {
938 eb = *ebtail = nasm_malloc(sizeof(*eb));
939 eb->next = NULL;
940 ebtail = &eb->next;
942 i -= EXT_BLKSIZ;
944 eb->exts[i] = ext;
945 ext->index = ++externals;
947 if (special && !used_special)
948 error(ERR_NONFATAL, "OBJ supports no special symbol features"
949 " for this symbol type");
952 static void obj_out (long segto, void *data, unsigned long type,
953 long segment, long wrt)
955 long size;
956 unsigned long realtype;
957 unsigned char *ucdata;
958 long ldata;
959 struct Segment *seg;
960 ObjRecord *orp;
963 * handle absolute-assembly (structure definitions)
965 if (segto == NO_SEG) {
966 if ((type & OUT_TYPMASK) != OUT_RESERVE)
967 error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
968 " space");
969 return;
973 * If `any_segs' is still FALSE, we must define a default
974 * segment.
976 if (!any_segs) {
977 int tempint; /* ignored */
978 if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
979 error (ERR_PANIC, "strange segment conditions in OBJ driver");
983 * Find the segment we are targetting.
985 for (seg = seghead; seg; seg = seg->next)
986 if (seg->index == segto)
987 break;
988 if (!seg)
989 error (ERR_PANIC, "code directed to nonexistent segment?");
991 orp = seg->orp;
992 orp->parm[0] = seg->currentpos;
994 size = type & OUT_SIZMASK;
995 realtype = type & OUT_TYPMASK;
996 if (realtype == OUT_RAWDATA) {
997 ucdata = data;
998 while (size > 0) {
999 unsigned int len;
1000 orp = obj_check(seg->orp, 1);
1001 len = RECORD_MAX - orp->used;
1002 if ((long)len > size)
1003 len = size;
1004 memcpy (orp->buf+orp->used, ucdata, len);
1005 orp->committed = orp->used += len;
1006 orp->parm[0] = seg->currentpos += len;
1007 ucdata += len;
1008 size -= len;
1011 else if (realtype == OUT_ADDRESS || realtype == OUT_REL2ADR ||
1012 realtype == OUT_REL4ADR)
1014 int rsize;
1016 if (segment == NO_SEG && realtype != OUT_ADDRESS)
1017 error(ERR_NONFATAL, "relative call to absolute address not"
1018 " supported by OBJ format");
1019 if (segment >= SEG_ABS)
1020 error(ERR_NONFATAL, "far-absolute relocations not supported"
1021 " by OBJ format");
1022 ldata = *(long *)data;
1023 if (realtype == OUT_REL2ADR) {
1024 ldata += (size-2);
1025 size = 2;
1027 if (realtype == OUT_REL4ADR) {
1028 ldata += (size-4);
1029 size = 4;
1031 if (size == 2)
1032 orp = obj_word (orp, ldata);
1033 else
1034 orp = obj_dword (orp, ldata);
1035 rsize = size;
1036 if (segment < SEG_ABS && (segment != NO_SEG && segment % 2) &&
1037 size == 4) {
1039 * This is a 4-byte segment-base relocation such as
1040 * `MOV EAX,SEG foo'. OBJ format can't actually handle
1041 * these, but if the constant term has the 16 low bits
1042 * zero, we can just apply a 2-byte segment-base
1043 * relocation to the low word instead.
1045 rsize = 2;
1046 if (ldata & 0xFFFF)
1047 error(ERR_NONFATAL, "OBJ format cannot handle complex"
1048 " dword-size segment base references");
1050 if (segment != NO_SEG)
1051 obj_write_fixup (orp, rsize,
1052 (realtype == OUT_ADDRESS ? 0x4000 : 0),
1053 segment, wrt);
1054 seg->currentpos += size;
1055 } else if (realtype == OUT_RESERVE) {
1056 if (orp->committed)
1057 orp = obj_bump(orp);
1058 seg->currentpos += size;
1060 obj_commit(orp);
1063 static void obj_write_fixup (ObjRecord *orp, int bytes,
1064 int segrel, long seg, long wrt)
1066 int locat, method;
1067 int base;
1068 long tidx, fidx;
1069 struct Segment *s = NULL;
1070 struct Group *g = NULL;
1071 struct External *e = NULL;
1072 ObjRecord *forp;
1074 if (bytes == 1) {
1075 error(ERR_NONFATAL, "`obj' output driver does not support"
1076 " one-byte relocations");
1077 return;
1080 forp = orp->child;
1081 if (forp == NULL) {
1082 orp->child = forp = obj_new();
1083 forp->up = &(orp->child);
1084 forp->type = FIXUPP;
1087 if (seg % 2) {
1088 base = TRUE;
1089 locat = FIX_16_SELECTOR;
1090 seg--;
1091 if (bytes != 2)
1092 error(ERR_PANIC, "OBJ: 4-byte segment base fixup got"
1093 " through sanity check");
1095 else {
1096 base = FALSE;
1097 locat = (bytes == 2) ? FIX_16_OFFSET : FIX_32_OFFSET;
1098 if (!segrel)
1100 * There is a bug in tlink that makes it process self relative
1101 * fixups incorrectly if the x_size doesn't match the location
1102 * size.
1104 forp = obj_force(forp, bytes<<3);
1107 forp = obj_rword (forp, locat | segrel | (orp->parm[0]-orp->parm[2]));
1109 tidx = fidx = -1, method = 0; /* placate optimisers */
1112 * See if we can find the segment ID in our segment list. If
1113 * so, we have a T4 (LSEG) target.
1115 for (s = seghead; s; s = s->next)
1116 if (s->index == seg)
1117 break;
1118 if (s)
1119 method = 4, tidx = s->obj_index;
1120 else {
1121 for (g = grphead; g; g = g->next)
1122 if (g->index == seg)
1123 break;
1124 if (g)
1125 method = 5, tidx = g->obj_index;
1126 else {
1127 long i = seg/2;
1128 struct ExtBack *eb = ebhead;
1129 while (i > EXT_BLKSIZ) {
1130 if (eb)
1131 eb = eb->next;
1132 else
1133 break;
1134 i -= EXT_BLKSIZ;
1136 if (eb)
1137 method = 6, e = eb->exts[i], tidx = e->index;
1138 else
1139 error(ERR_PANIC,
1140 "unrecognised segment value in obj_write_fixup");
1145 * If no WRT given, assume the natural default, which is method
1146 * F5 unless:
1148 * - we are doing an OFFSET fixup for a grouped segment, in
1149 * which case we require F1 (group).
1151 * - we are doing an OFFSET fixup for an external with a
1152 * default WRT, in which case we must honour the default WRT.
1154 if (wrt == NO_SEG) {
1155 if (!base && s && s->grp)
1156 method |= 0x10, fidx = s->grp->obj_index;
1157 else if (!base && e && e->defwrt_type != DEFWRT_NONE) {
1158 if (e->defwrt_type == DEFWRT_SEGMENT)
1159 method |= 0x00, fidx = e->defwrt_ptr.seg->obj_index;
1160 else if (e->defwrt_type == DEFWRT_GROUP)
1161 method |= 0x10, fidx = e->defwrt_ptr.grp->obj_index;
1162 else {
1163 error(ERR_NONFATAL, "default WRT specification for"
1164 " external `%s' unresolved", e->name);
1165 method |= 0x50, fidx = -1; /* got to do _something_ */
1167 } else
1168 method |= 0x50, fidx = -1;
1169 } else {
1171 * See if we can find the WRT-segment ID in our segment
1172 * list. If so, we have a F0 (LSEG) frame.
1174 for (s = seghead; s; s = s->next)
1175 if (s->index == wrt-1)
1176 break;
1177 if (s)
1178 method |= 0x00, fidx = s->obj_index;
1179 else {
1180 for (g = grphead; g; g = g->next)
1181 if (g->index == wrt-1)
1182 break;
1183 if (g)
1184 method |= 0x10, fidx = g->obj_index;
1185 else {
1186 long i = wrt/2;
1187 struct ExtBack *eb = ebhead;
1188 while (i > EXT_BLKSIZ) {
1189 if (eb)
1190 eb = eb->next;
1191 else
1192 break;
1193 i -= EXT_BLKSIZ;
1195 if (eb)
1196 method |= 0x20, fidx = eb->exts[i]->index;
1197 else
1198 error(ERR_PANIC,
1199 "unrecognised WRT value in obj_write_fixup");
1204 forp = obj_byte (forp, method);
1205 if (fidx != -1)
1206 forp = obj_index (forp, fidx);
1207 forp = obj_index (forp, tidx);
1208 obj_commit (forp);
1211 static long obj_segment (char *name, int pass, int *bits)
1214 * We call the label manager here to define a name for the new
1215 * segment, and when our _own_ label-definition stub gets
1216 * called in return, it should register the new segment name
1217 * using the pointer it gets passed. That way we save memory,
1218 * by sponging off the label manager.
1220 if (!name) {
1221 *bits = 16;
1222 return first_seg;
1223 } else {
1224 struct Segment *seg;
1225 struct Group *grp;
1226 struct External **extp;
1227 int obj_idx, i, attrs, rn_error;
1228 char *p;
1231 * Look for segment attributes.
1233 attrs = 0;
1234 while (*name == '.')
1235 name++; /* hack, but a documented one */
1236 p = name;
1237 while (*p && !isspace(*p))
1238 p++;
1239 if (*p) {
1240 *p++ = '\0';
1241 while (*p && isspace(*p))
1242 *p++ = '\0';
1244 while (*p) {
1245 while (*p && !isspace(*p))
1246 p++;
1247 if (*p) {
1248 *p++ = '\0';
1249 while (*p && isspace(*p))
1250 *p++ = '\0';
1253 attrs++;
1256 obj_idx = 1;
1257 for (seg = seghead; seg; seg = seg->next) {
1258 obj_idx++;
1259 if (!strcmp(seg->name, name)) {
1260 if (attrs > 0 && pass == 1)
1261 error(ERR_WARNING, "segment attributes specified on"
1262 " redeclaration of segment: ignoring");
1263 if (seg->use32)
1264 *bits = 32;
1265 else
1266 *bits = 16;
1267 return seg->index;
1271 *segtail = seg = nasm_malloc(sizeof(*seg));
1272 seg->next = NULL;
1273 segtail = &seg->next;
1274 seg->index = (any_segs ? seg_alloc() : first_seg);
1275 seg->obj_index = obj_idx;
1276 seg->grp = NULL;
1277 any_segs = TRUE;
1278 seg->name = NULL;
1279 seg->currentpos = 0;
1280 seg->align = 1; /* default */
1281 seg->use32 = FALSE; /* default */
1282 seg->combine = CMB_PUBLIC; /* default */
1283 seg->segclass = seg->overlay = NULL;
1284 seg->pubhead = NULL;
1285 seg->pubtail = &seg->pubhead;
1286 seg->lochead = NULL;
1287 seg->loctail = &seg->lochead;
1288 seg->orp = obj_new();
1289 seg->orp->up = &(seg->orp);
1290 seg->orp->ori = ori_ledata;
1291 seg->orp->type = LEDATA;
1292 seg->orp->parm[1] = obj_idx;
1295 * Process the segment attributes.
1297 p = name;
1298 while (attrs--) {
1299 p += strlen(p);
1300 while (!*p) p++;
1303 * `p' contains a segment attribute.
1305 if (!nasm_stricmp(p, "private"))
1306 seg->combine = CMB_PRIVATE;
1307 else if (!nasm_stricmp(p, "public"))
1308 seg->combine = CMB_PUBLIC;
1309 else if (!nasm_stricmp(p, "common"))
1310 seg->combine = CMB_COMMON;
1311 else if (!nasm_stricmp(p, "stack"))
1312 seg->combine = CMB_STACK;
1313 else if (!nasm_stricmp(p, "use16"))
1314 seg->use32 = FALSE;
1315 else if (!nasm_stricmp(p, "use32"))
1316 seg->use32 = TRUE;
1317 else if (!nasm_stricmp(p, "flat")) {
1319 * This segment is an OS/2 FLAT segment. That means
1320 * that its default group is group FLAT, even if
1321 * the group FLAT does not explicitly _contain_ the
1322 * segment.
1324 * When we see this, we must create the group
1325 * `FLAT', containing no segments, if it does not
1326 * already exist; then we must set the default
1327 * group of this segment to be the FLAT group.
1329 struct Group *grp;
1330 for (grp = grphead; grp; grp = grp->next)
1331 if (!strcmp(grp->name, "FLAT"))
1332 break;
1333 if (!grp) {
1334 obj_directive ("group", "FLAT", 1);
1335 for (grp = grphead; grp; grp = grp->next)
1336 if (!strcmp(grp->name, "FLAT"))
1337 break;
1338 if (!grp)
1339 error (ERR_PANIC, "failure to define FLAT?!");
1341 seg->grp = grp;
1342 } else if (!nasm_strnicmp(p, "class=", 6))
1343 seg->segclass = nasm_strdup(p+6);
1344 else if (!nasm_strnicmp(p, "overlay=", 8))
1345 seg->overlay = nasm_strdup(p+8);
1346 else if (!nasm_strnicmp(p, "align=", 6)) {
1347 seg->align = readnum(p+6, &rn_error);
1348 if (rn_error) {
1349 seg->align = 1;
1350 error (ERR_NONFATAL, "segment alignment should be"
1351 " numeric");
1353 switch ((int) seg->align) {
1354 case 1: /* BYTE */
1355 case 2: /* WORD */
1356 case 4: /* DWORD */
1357 case 16: /* PARA */
1358 case 256: /* PAGE */
1359 case 4096: /* PharLap extension */
1360 break;
1361 case 8:
1362 error(ERR_WARNING, "OBJ format does not support alignment"
1363 " of 8: rounding up to 16");
1364 seg->align = 16;
1365 break;
1366 case 32:
1367 case 64:
1368 case 128:
1369 error(ERR_WARNING, "OBJ format does not support alignment"
1370 " of %d: rounding up to 256", seg->align);
1371 seg->align = 256;
1372 break;
1373 case 512:
1374 case 1024:
1375 case 2048:
1376 error(ERR_WARNING, "OBJ format does not support alignment"
1377 " of %d: rounding up to 4096", seg->align);
1378 seg->align = 4096;
1379 break;
1380 default:
1381 error(ERR_NONFATAL, "invalid alignment value %d",
1382 seg->align);
1383 seg->align = 1;
1384 break;
1386 } else if (!nasm_strnicmp(p, "absolute=", 9)) {
1387 seg->align = SEG_ABS + readnum(p+9, &rn_error);
1388 if (rn_error)
1389 error (ERR_NONFATAL, "argument to `absolute' segment"
1390 " attribute should be numeric");
1394 obj_seg_needs_update = seg;
1395 if (seg->align >= SEG_ABS)
1396 deflabel (name, NO_SEG, seg->align - SEG_ABS,
1397 NULL, FALSE, FALSE, &of_obj, error);
1398 else
1399 deflabel (name, seg->index+1, 0L,
1400 NULL, FALSE, FALSE, &of_obj, error);
1401 obj_seg_needs_update = NULL;
1404 * See if this segment is defined in any groups.
1406 for (grp = grphead; grp; grp = grp->next) {
1407 for (i = grp->nindices; i < grp->nentries; i++) {
1408 if (!strcmp(grp->segs[i].name, seg->name)) {
1409 nasm_free (grp->segs[i].name);
1410 grp->segs[i] = grp->segs[grp->nindices];
1411 grp->segs[grp->nindices++].index = seg->obj_index;
1412 if (seg->grp)
1413 error(ERR_WARNING, "segment `%s' is already part of"
1414 " a group: first one takes precedence",
1415 seg->name);
1416 else
1417 seg->grp = grp;
1423 * Walk through the list of externals with unresolved
1424 * default-WRT clauses, and resolve any that point at this
1425 * segment.
1427 extp = &dws;
1428 while (*extp) {
1429 if ((*extp)->defwrt_type == DEFWRT_STRING &&
1430 !strcmp((*extp)->defwrt_ptr.string, seg->name)) {
1431 nasm_free((*extp)->defwrt_ptr.string);
1432 (*extp)->defwrt_type = DEFWRT_SEGMENT;
1433 (*extp)->defwrt_ptr.seg = seg;
1434 *extp = (*extp)->next_dws;
1435 } else
1436 extp = &(*extp)->next_dws;
1439 if (seg->use32)
1440 *bits = 32;
1441 else
1442 *bits = 16;
1443 return seg->index;
1447 static int obj_directive (char *directive, char *value, int pass)
1449 if (!strcmp(directive, "group")) {
1450 char *p, *q, *v;
1451 if (pass == 1) {
1452 struct Group *grp;
1453 struct Segment *seg;
1454 struct External **extp;
1455 int obj_idx;
1457 q = value;
1458 while (*q == '.')
1459 q++; /* hack, but a documented one */
1460 v = q;
1461 while (*q && !isspace(*q))
1462 q++;
1463 if (isspace(*q)) {
1464 *q++ = '\0';
1465 while (*q && isspace(*q))
1466 q++;
1469 * Here we used to sanity-check the group directive to
1470 * ensure nobody tried to declare a group containing no
1471 * segments. However, OS/2 does this as standard
1472 * practice, so the sanity check has been removed.
1474 * if (!*q) {
1475 * error(ERR_NONFATAL,"GROUP directive contains no segments");
1476 * return 1;
1480 obj_idx = 1;
1481 for (grp = grphead; grp; grp = grp->next) {
1482 obj_idx++;
1483 if (!strcmp(grp->name, v)) {
1484 error(ERR_NONFATAL, "group `%s' defined twice", v);
1485 return 1;
1489 *grptail = grp = nasm_malloc(sizeof(*grp));
1490 grp->next = NULL;
1491 grptail = &grp->next;
1492 grp->index = seg_alloc();
1493 grp->obj_index = obj_idx;
1494 grp->nindices = grp->nentries = 0;
1495 grp->name = NULL;
1497 obj_grp_needs_update = grp;
1498 deflabel (v, grp->index+1, 0L,
1499 NULL, FALSE, FALSE, &of_obj, error);
1500 obj_grp_needs_update = NULL;
1502 while (*q) {
1503 p = q;
1504 while (*q && !isspace(*q))
1505 q++;
1506 if (isspace(*q)) {
1507 *q++ = '\0';
1508 while (*q && isspace(*q))
1509 q++;
1512 * Now p contains a segment name. Find it.
1514 for (seg = seghead; seg; seg = seg->next)
1515 if (!strcmp(seg->name, p))
1516 break;
1517 if (seg) {
1519 * We have a segment index. Shift a name entry
1520 * to the end of the array to make room.
1522 grp->segs[grp->nentries++] = grp->segs[grp->nindices];
1523 grp->segs[grp->nindices++].index = seg->obj_index;
1524 if (seg->grp)
1525 error(ERR_WARNING, "segment `%s' is already part of"
1526 " a group: first one takes precedence",
1527 seg->name);
1528 else
1529 seg->grp = grp;
1530 } else {
1532 * We have an as-yet undefined segment.
1533 * Remember its name, for later.
1535 grp->segs[grp->nentries++].name = nasm_strdup(p);
1540 * Walk through the list of externals with unresolved
1541 * default-WRT clauses, and resolve any that point at
1542 * this group.
1544 extp = &dws;
1545 while (*extp) {
1546 if ((*extp)->defwrt_type == DEFWRT_STRING &&
1547 !strcmp((*extp)->defwrt_ptr.string, grp->name)) {
1548 nasm_free((*extp)->defwrt_ptr.string);
1549 (*extp)->defwrt_type = DEFWRT_GROUP;
1550 (*extp)->defwrt_ptr.grp = grp;
1551 *extp = (*extp)->next_dws;
1552 } else
1553 extp = &(*extp)->next_dws;
1556 return 1;
1558 if (!strcmp(directive, "uppercase")) {
1559 obj_uppercase = TRUE;
1560 return 1;
1562 if (!strcmp(directive, "import")) {
1563 char *q, *extname, *libname, *impname;
1565 if (pass == 2)
1566 return 1; /* ignore in pass two */
1567 extname = q = value;
1568 while (*q && !isspace(*q))
1569 q++;
1570 if (isspace(*q)) {
1571 *q++ = '\0';
1572 while (*q && isspace(*q))
1573 q++;
1576 libname = q;
1577 while (*q && !isspace(*q))
1578 q++;
1579 if (isspace(*q)) {
1580 *q++ = '\0';
1581 while (*q && isspace(*q))
1582 q++;
1585 impname = q;
1587 if (!*extname || !*libname)
1588 error(ERR_NONFATAL, "`import' directive requires symbol name"
1589 " and library name");
1590 else {
1591 struct ImpDef *imp;
1592 int err = FALSE;
1594 imp = *imptail = nasm_malloc(sizeof(struct ImpDef));
1595 imptail = &imp->next;
1596 imp->next = NULL;
1597 imp->extname = nasm_strdup(extname);
1598 imp->libname = nasm_strdup(libname);
1599 imp->impindex = readnum(impname, &err);
1600 if (!*impname || err)
1601 imp->impname = nasm_strdup(impname);
1602 else
1603 imp->impname = NULL;
1606 return 1;
1608 if (!strcmp(directive, "export")) {
1609 char *q, *extname, *intname, *v;
1610 struct ExpDef *export;
1611 int flags = 0;
1612 unsigned int ordinal = 0;
1614 if (pass == 2)
1615 return 1; /* ignore in pass two */
1616 intname = q = value;
1617 while (*q && !isspace(*q))
1618 q++;
1619 if (isspace(*q)) {
1620 *q++ = '\0';
1621 while (*q && isspace(*q))
1622 q++;
1625 extname = q;
1626 while (*q && !isspace(*q))
1627 q++;
1628 if (isspace(*q)) {
1629 *q++ = '\0';
1630 while (*q && isspace(*q))
1631 q++;
1634 if (!*intname) {
1635 error(ERR_NONFATAL, "`export' directive requires export name");
1636 return 1;
1638 if (!*extname) {
1639 extname = intname;
1640 intname = "";
1642 while (*q) {
1643 v = q;
1644 while (*q && !isspace(*q))
1645 q++;
1646 if (isspace(*q)) {
1647 *q++ = '\0';
1648 while (*q && isspace(*q))
1649 q++;
1651 if (!nasm_stricmp(v, "resident"))
1652 flags |= EXPDEF_FLAG_RESIDENT;
1653 else if (!nasm_stricmp(v, "nodata"))
1654 flags |= EXPDEF_FLAG_NODATA;
1655 else if (!nasm_strnicmp(v, "parm=", 5)) {
1656 int err = FALSE;
1657 flags |= EXPDEF_MASK_PARMCNT & readnum(v+5, &err);
1658 if (err) {
1659 error(ERR_NONFATAL,
1660 "value `%s' for `parm' is non-numeric", v+5);
1661 return 1;
1663 } else {
1664 int err = FALSE;
1665 ordinal = readnum(v, &err);
1666 if (err) {
1667 error(ERR_NONFATAL, "unrecognised export qualifier `%s'",
1669 return 1;
1671 flags |= EXPDEF_FLAG_ORDINAL;
1675 export = *exptail = nasm_malloc(sizeof(struct ExpDef));
1676 exptail = &export->next;
1677 export->next = NULL;
1678 export->extname = nasm_strdup(extname);
1679 export->intname = nasm_strdup(intname);
1680 export->ordinal = ordinal;
1681 export->flags = flags;
1683 return 1;
1685 return 0;
1688 static long obj_segbase (long segment)
1690 struct Segment *seg;
1693 * Find the segment in our list.
1695 for (seg = seghead; seg; seg = seg->next)
1696 if (seg->index == segment-1)
1697 break;
1699 if (!seg) {
1701 * Might be an external with a default WRT.
1703 long i = segment/2;
1704 struct ExtBack *eb = ebhead;
1705 struct External *e;
1707 while (i > EXT_BLKSIZ) {
1708 if (eb)
1709 eb = eb->next;
1710 else
1711 break;
1712 i -= EXT_BLKSIZ;
1714 if (eb) {
1715 e = eb->exts[i];
1716 if (e->defwrt_type == DEFWRT_NONE)
1717 return segment; /* fine */
1718 else if (e->defwrt_type == DEFWRT_SEGMENT)
1719 return e->defwrt_ptr.seg->index+1;
1720 else if (e->defwrt_type == DEFWRT_GROUP)
1721 return e->defwrt_ptr.grp->index+1;
1722 else
1723 return NO_SEG; /* can't tell what it is */
1726 return segment; /* not one of ours - leave it alone */
1729 if (seg->align >= SEG_ABS)
1730 return seg->align; /* absolute segment */
1731 if (seg->grp)
1732 return seg->grp->index+1; /* grouped segment */
1734 return segment; /* no special treatment */
1737 static void obj_filename (char *inname, char *outname, efunc error)
1739 strcpy(obj_infile, inname);
1740 standard_extension (inname, outname, ".obj", error);
1743 static void obj_write_file (int debuginfo)
1745 struct Segment *seg, *entry_seg_ptr = 0;
1746 struct FileName *fn;
1747 struct LineNumber *ln;
1748 struct Group *grp;
1749 struct Public *pub, *loc;
1750 struct External *ext;
1751 struct ImpDef *imp;
1752 struct ExpDef *export;
1753 static char boast[] = "The Netwide Assembler " NASM_VER;
1754 int lname_idx;
1755 ObjRecord *orp;
1758 * Write the THEADR module header.
1760 orp = obj_new();
1761 orp->type = THEADR;
1762 obj_name (orp, obj_infile);
1763 obj_emit2 (orp);
1766 * Write the NASM boast comment.
1768 orp->type = COMENT;
1769 obj_rword (orp, 0); /* comment type zero */
1770 obj_name (orp, boast);
1771 obj_emit2 (orp);
1773 orp->type = COMENT;
1775 * Write the IMPDEF records, if any.
1777 for (imp = imphead; imp; imp = imp->next) {
1778 obj_rword (orp, 0xA0); /* comment class A0 */
1779 obj_byte (orp, 1); /* subfunction 1: IMPDEF */
1780 if (imp->impname)
1781 obj_byte (orp, 0); /* import by name */
1782 else
1783 obj_byte (orp, 1); /* import by ordinal */
1784 obj_name (orp, imp->extname);
1785 obj_name (orp, imp->libname);
1786 if (imp->impname)
1787 obj_name (orp, imp->impname);
1788 else
1789 obj_word (orp, imp->impindex);
1790 obj_emit2 (orp);
1794 * Write the EXPDEF records, if any.
1796 for (export = exphead; export; export = export->next) {
1797 obj_rword (orp, 0xA0); /* comment class A0 */
1798 obj_byte (orp, 2); /* subfunction 2: EXPDEF */
1799 obj_byte (orp, export->flags);
1800 obj_name (orp, export->extname);
1801 obj_name (orp, export->intname);
1802 if (export->flags & EXPDEF_FLAG_ORDINAL)
1803 obj_word (orp, export->ordinal);
1804 obj_emit2 (orp);
1807 /* we're using extended OMF if we put in debug info*/
1808 if (debuginfo) {
1809 orp->type = COMENT;
1810 obj_byte (orp, 0x40);
1811 obj_byte (orp, dEXTENDED);
1812 obj_emit2 (orp);
1816 * Write the first LNAMES record, containing LNAME one, which
1817 * is null. Also initialise the LNAME counter.
1819 orp->type = LNAMES;
1820 obj_byte (orp, 0);
1821 lname_idx = 1;
1823 * Write some LNAMES for the segment names
1825 for (seg = seghead; seg; seg = seg->next) {
1826 orp = obj_name (orp, seg->name);
1827 if (seg->segclass)
1828 orp = obj_name (orp, seg->segclass);
1829 if (seg->overlay)
1830 orp = obj_name (orp, seg->overlay);
1831 obj_commit (orp);
1834 * Write some LNAMES for the group names
1836 for (grp = grphead; grp; grp = grp->next) {
1837 orp = obj_name (orp, grp->name);
1838 obj_commit (orp);
1840 obj_emit (orp);
1844 * Write the SEGDEF records.
1846 orp->type = SEGDEF;
1847 for (seg = seghead; seg; seg = seg->next) {
1848 int acbp;
1849 unsigned long seglen = seg->currentpos;
1851 acbp = (seg->combine << 2); /* C field */
1853 if (seg->use32)
1854 acbp |= 0x01; /* P bit is Use32 flag */
1855 else if (seglen == 0x10000L) {
1856 seglen = 0; /* This special case may be needed for old linkers */
1857 acbp |= 0x02; /* B bit */
1861 /* A field */
1862 if (seg->align >= SEG_ABS)
1863 /* acbp |= 0x00 */;
1864 else if (seg->align >= 4096) {
1865 if (seg->align > 4096)
1866 error(ERR_NONFATAL, "segment `%s' requires more alignment"
1867 " than OBJ format supports", seg->name);
1868 acbp |= 0xC0; /* PharLap extension */
1869 } else if (seg->align >= 256) {
1870 acbp |= 0x80;
1871 } else if (seg->align >= 16) {
1872 acbp |= 0x60;
1873 } else if (seg->align >= 4) {
1874 acbp |= 0xA0;
1875 } else if (seg->align >= 2) {
1876 acbp |= 0x40;
1877 } else
1878 acbp |= 0x20;
1880 obj_byte (orp, acbp);
1881 if (seg->align & SEG_ABS) {
1882 obj_x (orp, seg->align - SEG_ABS); /* Frame */
1883 obj_byte (orp, 0); /* Offset */
1885 obj_x (orp, seglen);
1886 obj_index (orp, ++lname_idx);
1887 obj_index (orp, seg->segclass ? ++lname_idx : 1);
1888 obj_index (orp, seg->overlay ? ++lname_idx : 1);
1889 obj_emit2 (orp);
1893 * Write the GRPDEF records.
1895 orp->type = GRPDEF;
1896 for (grp = grphead; grp; grp = grp->next) {
1897 int i;
1899 if (grp->nindices != grp->nentries) {
1900 for (i = grp->nindices; i < grp->nentries; i++) {
1901 error(ERR_NONFATAL, "group `%s' contains undefined segment"
1902 " `%s'", grp->name, grp->segs[i].name);
1903 nasm_free (grp->segs[i].name);
1904 grp->segs[i].name = NULL;
1907 obj_index (orp, ++lname_idx);
1908 for (i = 0; i < grp->nindices; i++) {
1909 obj_byte (orp, 0xFF);
1910 obj_index (orp, grp->segs[i].index);
1912 obj_emit2 (orp);
1916 * Write the PUBDEF records: first the ones in the segments,
1917 * then the far-absolutes.
1919 orp->type = PUBDEF;
1920 orp->ori = ori_pubdef;
1921 for (seg = seghead; seg; seg = seg->next) {
1922 orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
1923 orp->parm[1] = seg->obj_index;
1924 for (pub = seg->pubhead; pub; pub = pub->next) {
1925 orp = obj_name (orp, pub->name);
1926 orp = obj_x (orp, pub->offset);
1927 orp = obj_byte (orp, 0); /* type index */
1928 obj_commit (orp);
1930 obj_emit (orp);
1932 orp->parm[0] = 0;
1933 orp->parm[1] = 0;
1934 for (pub = fpubhead; pub; pub = pub->next) { /* pub-crawl :-) */
1935 if ((long)orp->parm[2] != pub->segment) {
1936 obj_emit (orp);
1937 orp->parm[2] = pub->segment;
1939 orp = obj_name (orp, pub->name);
1940 orp = obj_x (orp, pub->offset);
1941 orp = obj_byte (orp, 0); /* type index */
1942 obj_commit (orp);
1944 obj_emit (orp);
1947 * Write the EXTDEF and COMDEF records, in order.
1949 orp->ori = ori_null;
1950 for (ext = exthead; ext; ext = ext->next) {
1951 if (ext->commonsize == 0) {
1952 if (orp->type != EXTDEF) {
1953 obj_emit (orp);
1954 orp->type = EXTDEF;
1956 orp = obj_name (orp, ext->name);
1957 orp = obj_index (orp, 0);
1958 } else {
1959 if (orp->type != COMDEF) {
1960 obj_emit (orp);
1961 orp->type = COMDEF;
1963 orp = obj_name (orp, ext->name);
1964 orp = obj_index (orp, 0);
1965 if (ext->commonelem) {
1966 orp = obj_byte (orp, 0x61);/* far communal */
1967 orp = obj_value (orp, (ext->commonsize / ext->commonelem));
1968 orp = obj_value (orp, ext->commonelem);
1969 } else {
1970 orp = obj_byte (orp, 0x62);/* near communal */
1971 orp = obj_value (orp, ext->commonsize);
1974 obj_commit (orp);
1976 obj_emit (orp);
1979 * Write a COMENT record stating that the linker's first pass
1980 * may stop processing at this point. Exception is if our
1981 * MODEND record specifies a start point, in which case,
1982 * according to some variants of the documentation, this COMENT
1983 * should be omitted. So we'll omit it just in case.
1984 * But, TASM puts it in all the time so if we are using
1985 * TASM debug stuff we are putting it in
1987 if (debuginfo || obj_entry_seg == NO_SEG) {
1988 orp->type = COMENT;
1989 obj_byte (orp, 0x40);
1990 obj_byte (orp, dLINKPASS);
1991 obj_byte (orp, 1);
1992 obj_emit2 (orp);
1996 * 1) put out the compiler type
1997 * 2) Put out the type info. The only type we are using is near label #19
1999 if (debuginfo) {
2000 int i;
2001 struct Array *arrtmp = arrhead;
2002 orp->type = COMENT;
2003 obj_byte (orp, 0x40);
2004 obj_byte (orp, dCOMPDEF);
2005 obj_byte (orp, 4);
2006 obj_byte (orp, 0);
2007 obj_emit2 (orp);
2009 obj_byte (orp, 0x40);
2010 obj_byte (orp, dTYPEDEF);
2011 obj_word (orp, 0x18); /* type # for linking */
2012 obj_word (orp, 6); /* size of type */
2013 obj_byte (orp, 0x2a); /* absolute type for debugging */
2014 obj_emit2 (orp);
2015 obj_byte (orp, 0x40);
2016 obj_byte (orp, dTYPEDEF);
2017 obj_word (orp, 0x19); /* type # for linking */
2018 obj_word (orp, 0); /* size of type */
2019 obj_byte (orp, 0x24); /* absolute type for debugging */
2020 obj_byte (orp, 0); /* near/far specifier */
2021 obj_emit2 (orp);
2022 obj_byte (orp, 0x40);
2023 obj_byte (orp, dTYPEDEF);
2024 obj_word (orp, 0x1A); /* type # for linking */
2025 obj_word (orp, 0); /* size of type */
2026 obj_byte (orp, 0x24); /* absolute type for debugging */
2027 obj_byte (orp, 1); /* near/far specifier */
2028 obj_emit2 (orp);
2029 obj_byte (orp, 0x40);
2030 obj_byte (orp, dTYPEDEF);
2031 obj_word (orp, 0x1b); /* type # for linking */
2032 obj_word (orp, 0); /* size of type */
2033 obj_byte (orp, 0x23); /* absolute type for debugging */
2034 obj_byte (orp, 0);
2035 obj_byte (orp, 0);
2036 obj_byte (orp, 0);
2037 obj_emit2 (orp);
2038 obj_byte (orp, 0x40);
2039 obj_byte (orp, dTYPEDEF);
2040 obj_word (orp, 0x1c); /* type # for linking */
2041 obj_word (orp, 0); /* size of type */
2042 obj_byte (orp, 0x23); /* absolute type for debugging */
2043 obj_byte (orp, 0);
2044 obj_byte (orp, 4);
2045 obj_byte (orp, 0);
2046 obj_emit2 (orp);
2047 obj_byte (orp, 0x40);
2048 obj_byte (orp, dTYPEDEF);
2049 obj_word (orp, 0x1d); /* type # for linking */
2050 obj_word (orp, 0); /* size of type */
2051 obj_byte (orp, 0x23); /* absolute type for debugging */
2052 obj_byte (orp, 0);
2053 obj_byte (orp, 1);
2054 obj_byte (orp, 0);
2055 obj_emit2 (orp);
2056 obj_byte (orp, 0x40);
2057 obj_byte (orp, dTYPEDEF);
2058 obj_word (orp, 0x1e); /* type # for linking */
2059 obj_word (orp, 0); /* size of type */
2060 obj_byte (orp, 0x23); /* absolute type for debugging */
2061 obj_byte (orp, 0);
2062 obj_byte (orp, 5);
2063 obj_byte (orp, 0);
2064 obj_emit2 (orp);
2066 /* put out the array types */
2067 for (i= ARRAYBOT; i < arrindex; i++) {
2068 obj_byte (orp, 0x40);
2069 obj_byte (orp, dTYPEDEF);
2070 obj_word (orp, i ); /* type # for linking */
2071 obj_word (orp, arrtmp->size); /* size of type */
2072 obj_byte (orp, 0x1A); /* absolute type for debugging (array)*/
2073 obj_byte (orp, arrtmp->basetype ); /* base type */
2074 obj_emit2 (orp);
2075 arrtmp = arrtmp->next ;
2079 * write out line number info with a LINNUM record
2080 * switch records when we switch segments, and output the
2081 * file in a pseudo-TASM fashion. The record switch is naive; that
2082 * is that one file may have many records for the same segment
2083 * if there are lots of segment switches
2085 if (fnhead && debuginfo) {
2086 seg = fnhead->lnhead->segment;
2088 for (fn = fnhead; fn; fn = fn->next) {
2089 /* write out current file name */
2090 orp->type = COMENT;
2091 orp->ori = ori_null;
2092 obj_byte (orp, 0x40);
2093 obj_byte (orp, dFILNAME);
2094 obj_byte( orp,0);
2095 obj_name( orp,fn->name);
2096 obj_dword(orp, 0);
2097 obj_emit2 (orp);
2099 /* write out line numbers this file */
2101 orp->type = LINNUM;
2102 orp->ori = ori_linnum;
2103 for (ln = fn->lnhead; ln; ln = ln->next) {
2104 if (seg != ln->segment) {
2105 /* if we get here have to flush the buffer and start
2106 * a new record for a new segment
2108 seg = ln->segment;
2109 obj_emit ( orp );
2111 orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
2112 orp->parm[1] = seg->obj_index;
2113 orp = obj_word(orp, ln->lineno);
2114 orp = obj_x(orp, ln->offset);
2115 obj_commit (orp);
2117 obj_emit (orp);
2121 * we are going to locate the entry point segment now
2122 * rather than wait until the MODEND record, because,
2123 * then we can output a special symbol to tell where the
2124 * entry point is.
2127 if (obj_entry_seg != NO_SEG) {
2128 for (seg = seghead; seg; seg = seg->next) {
2129 if (seg->index == obj_entry_seg) {
2130 entry_seg_ptr = seg;
2131 break;
2134 if (!seg)
2135 error(ERR_NONFATAL, "entry point is not in this module");
2139 * get ready to put out symbol records
2141 orp->type = COMENT;
2142 orp->ori = ori_local;
2145 * put out a symbol for the entry point
2146 * no dots in this symbol, because, borland does
2147 * not (officially) support dots in label names
2148 * and I don't know what various versions of TLINK will do
2150 if (debuginfo && obj_entry_seg != NO_SEG) {
2151 orp = obj_name (orp,"start_of_program");
2152 orp = obj_word (orp,0x19); /* type: near label */
2153 orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
2154 orp = obj_index (orp, seg->obj_index);
2155 orp = obj_x (orp, obj_entry_ofs);
2156 obj_commit (orp);
2160 * put out the local labels
2162 for (seg = seghead; seg && debuginfo; seg = seg->next) {
2163 /* labels this seg */
2164 for (loc = seg->lochead; loc; loc = loc->next) {
2165 orp = obj_name (orp,loc->name);
2166 orp = obj_word (orp, loc->type);
2167 orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
2168 orp = obj_index (orp, seg->obj_index);
2169 orp = obj_x (orp,loc->offset);
2170 obj_commit (orp);
2173 if (orp->used)
2174 obj_emit (orp);
2177 * Write the LEDATA/FIXUPP pairs.
2179 for (seg = seghead; seg; seg = seg->next) {
2180 obj_emit (seg->orp);
2181 nasm_free (seg->orp);
2185 * Write the MODEND module end marker.
2187 orp->type = MODEND;
2188 orp->ori = ori_null;
2189 if (entry_seg_ptr) {
2190 obj_byte (orp, 0xC1);
2191 seg = entry_seg_ptr;
2192 if (seg->grp) {
2193 obj_byte (orp, 0x10);
2194 obj_index (orp, seg->grp->obj_index);
2195 } else {
2197 * the below changed to prevent TLINK crashing.
2198 * Previous more efficient version read:
2200 * obj_byte (orp, 0x50);
2202 obj_byte (orp, 0x00);
2203 obj_index (orp, seg->obj_index);
2205 obj_index (orp, seg->obj_index);
2206 obj_x (orp, obj_entry_ofs);
2207 } else
2208 obj_byte (orp, 0);
2209 obj_emit2 (orp);
2210 nasm_free (orp);
2213 void obj_fwrite(ObjRecord *orp)
2215 unsigned int cksum, len;
2216 unsigned char *ptr;
2218 cksum = orp->type;
2219 if (orp->x_size == 32)
2220 cksum |= 1;
2221 fputc (cksum, ofp);
2222 len = orp->committed+1;
2223 cksum += (len & 0xFF) + ((len>>8) & 0xFF);
2224 fwriteshort (len, ofp);
2225 fwrite (orp->buf, 1, len-1, ofp);
2226 for (ptr=orp->buf; --len; ptr++)
2227 cksum += *ptr;
2228 fputc ( (-cksum) & 0xFF, ofp);
2231 static char *obj_stdmac[] = {
2232 "%define __SECT__ [section .text]",
2233 "%imacro group 1+.nolist",
2234 "[group %1]",
2235 "%endmacro",
2236 "%imacro uppercase 0+.nolist",
2237 "[uppercase %1]",
2238 "%endmacro",
2239 "%imacro export 1+.nolist",
2240 "[export %1]",
2241 "%endmacro",
2242 "%imacro import 1+.nolist",
2243 "[import %1]",
2244 "%endmacro",
2245 "%macro __NASM_CDecl__ 1",
2246 "%endmacro",
2247 NULL
2250 void dbgbi_init(struct ofmt * of, void * id, FILE * fp, efunc error)
2252 (void) of;
2253 (void) id;
2254 (void) fp;
2255 (void) error;
2257 fnhead = NULL;
2258 fntail = &fnhead;
2259 arrindex = ARRAYBOT ;
2260 arrhead = NULL;
2261 arrtail = &arrhead;
2263 static void dbgbi_cleanup(void)
2265 struct Segment *segtmp;
2266 while (fnhead) {
2267 struct FileName *fntemp = fnhead;
2268 while (fnhead->lnhead) {
2269 struct LineNumber *lntemp = fnhead->lnhead;
2270 fnhead->lnhead = lntemp->next;
2271 nasm_free( lntemp);
2273 fnhead = fnhead->next;
2274 nasm_free (fntemp->name);
2275 nasm_free (fntemp);
2277 for (segtmp=seghead; segtmp; segtmp=segtmp->next) {
2278 while (segtmp->lochead) {
2279 struct Public *loctmp = segtmp->lochead;
2280 segtmp->lochead = loctmp->next;
2281 nasm_free (loctmp->name);
2282 nasm_free (loctmp);
2285 while (arrhead) {
2286 struct Array *arrtmp = arrhead;
2287 arrhead = arrhead->next;
2288 nasm_free (arrtmp);
2292 static void dbgbi_linnum (const char *lnfname, long lineno, long segto)
2294 struct FileName *fn;
2295 struct LineNumber *ln;
2296 struct Segment *seg;
2298 if (segto == NO_SEG)
2299 return;
2302 * If `any_segs' is still FALSE, we must define a default
2303 * segment.
2305 if (!any_segs) {
2306 int tempint; /* ignored */
2307 if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
2308 error (ERR_PANIC, "strange segment conditions in OBJ driver");
2312 * Find the segment we are targetting.
2314 for (seg = seghead; seg; seg = seg->next)
2315 if (seg->index == segto)
2316 break;
2317 if (!seg)
2318 error (ERR_PANIC, "lineno directed to nonexistent segment?");
2320 for (fn = fnhead; fn; fn = fn->next) /*bf*/
2321 if (!nasm_stricmp(lnfname,fn->name))
2322 break;
2323 if (!fn) {
2324 fn = nasm_malloc ( sizeof( *fn));
2325 fn->name = nasm_malloc ( strlen(lnfname) + 1) ;
2326 strcpy (fn->name,lnfname);
2327 fn->lnhead = NULL;
2328 fn->lntail = & fn->lnhead;
2329 fn->next = NULL;
2330 *fntail = fn;
2331 fntail = &fn->next;
2333 ln = nasm_malloc ( sizeof( *ln));
2334 ln->segment = seg;
2335 ln->offset = seg->currentpos;
2336 ln->lineno = lineno;
2337 ln->next = NULL;
2338 *fn->lntail = ln;
2339 fn->lntail = &ln->next;
2342 static void dbgbi_deflabel (char *name, long segment,
2343 long offset, int is_global, char *special)
2345 struct Segment *seg;
2347 (void) special;
2350 * If it's a special-retry from pass two, discard it.
2352 if (is_global == 3)
2353 return;
2356 * First check for the double-period, signifying something
2357 * unusual.
2359 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
2360 return;
2364 * Case (i):
2366 if (obj_seg_needs_update) {
2367 return;
2368 } else if (obj_grp_needs_update) {
2369 return;
2371 if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
2372 return;
2374 if (segment >= SEG_ABS || segment == NO_SEG) {
2375 return;
2379 * If `any_segs' is still FALSE, we might need to define a
2380 * default segment, if they're trying to declare a label in
2381 * `first_seg'. But the label should exist due to a prior
2382 * call to obj_deflabel so we can skip that.
2385 for (seg = seghead; seg; seg = seg->next)
2386 if (seg->index == segment) {
2387 struct Public *loc = nasm_malloc (sizeof(*loc));
2389 * Case (ii). Maybe MODPUB someday?
2391 last_defined = *seg->loctail = loc;
2392 seg->loctail = &loc->next;
2393 loc->next = NULL;
2394 loc->name = nasm_strdup(name);
2395 loc->offset = offset;
2398 static void dbgbi_typevalue (long type)
2400 int vsize;
2401 int elem = TYM_ELEMENTS(type);
2402 type = TYM_TYPE(type);
2404 if (!last_defined)
2405 return;
2407 switch (type) {
2408 case TY_BYTE:
2409 last_defined->type = 8; /* unsigned char */
2410 vsize = 1;
2411 break;
2412 case TY_WORD:
2413 last_defined->type = 10; /* unsigned word */
2414 vsize = 2;
2415 break;
2416 case TY_DWORD:
2417 last_defined->type = 12; /* unsigned dword */
2418 vsize = 4;
2419 break;
2420 case TY_FLOAT:
2421 last_defined->type = 14; /* float */
2422 vsize = 4;
2423 break;
2424 case TY_QWORD:
2425 last_defined->type = 15; /* qword */
2426 vsize = 8;
2427 break;
2428 case TY_TBYTE:
2429 last_defined->type = 16; /* TBYTE */
2430 vsize = 10;
2431 break;
2432 default:
2433 last_defined->type = 0x19; /*label */
2434 vsize = 0;
2435 break;
2438 if (elem > 1) {
2439 struct Array *arrtmp = nasm_malloc (sizeof(*arrtmp));
2440 int vtype = last_defined->type;
2441 arrtmp->size = vsize * elem;
2442 arrtmp->basetype = vtype;
2443 arrtmp->next = NULL;
2444 last_defined->type = arrindex++;
2445 *arrtail = arrtmp;
2446 arrtail = & (arrtmp->next);
2448 last_defined = NULL;
2450 static void dbgbi_output (int output_type, void *param)
2452 (void) output_type;
2453 (void) param;
2455 static struct dfmt borland_debug_form = {
2456 "Borland Debug Records",
2457 "borland",
2458 dbgbi_init,
2459 dbgbi_linnum,
2460 dbgbi_deflabel,
2461 null_debug_routine,
2462 dbgbi_typevalue,
2463 dbgbi_output,
2464 dbgbi_cleanup,
2467 static struct dfmt *borland_debug_arr[3] = {
2468 &borland_debug_form,
2469 &null_debug_form,
2470 NULL
2473 struct ofmt of_obj = {
2474 "MS-DOS 16-bit/32-bit OMF object files",
2475 "obj",
2476 NULL,
2477 borland_debug_arr,
2478 &null_debug_form,
2479 obj_stdmac,
2480 obj_init,
2481 obj_set_info,
2482 obj_out,
2483 obj_deflabel,
2484 obj_segment,
2485 obj_segbase,
2486 obj_directive,
2487 obj_filename,
2488 obj_cleanup
2490 #endif /* OF_OBJ */