NASM 0.98.03
[nasm/avx512.git] / outobj.c
blobf4619d9ef5cb6b5085fbe75b34d57df3d7d9fa9a
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-3 /* maximal size of any record except type+reclen */
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) */
106 FIXU32 = 0x9D, /* 32-bit fixups (relocations) */
108 MODEND = 0x8A /* module end */
111 enum ComentID { /* ID codes for comment records */
113 dEXTENDED = 0xA1, /* tells that we are using translator-specific extensions */
114 dLINKPASS = 0xA2, /* link pass 2 marker */
115 dTYPEDEF = 0xE3, /* define a type */
116 dSYM = 0xE6, /* symbol debug record */
117 dFILNAME = 0xE8, /* file name record */
118 dCOMPDEF = 0xEA /* compiler type info */
122 typedef struct ObjRecord ObjRecord;
123 typedef void ORI(ObjRecord *orp);
125 struct ObjRecord {
126 ORI *ori; /* Initialization routine */
127 int used; /* Current data size */
128 int committed; /* Data size at last boundary */
129 int x_size; /* (see obj_x) */
130 unsigned int type; /* Record type */
131 ObjRecord *child; /* Associated record below this one */
132 ObjRecord **up; /* Master pointer to this ObjRecord */
133 ObjRecord *back; /* Previous part of this record */
134 unsigned long parm[OBJ_PARMS]; /* Parameters for ori routine */
135 unsigned char buf[RECORD_MAX];
138 static void obj_fwrite(ObjRecord *orp);
139 static void ori_ledata(ObjRecord *orp);
140 static void ori_pubdef(ObjRecord *orp);
141 static void ori_null(ObjRecord *orp);
142 static ObjRecord *obj_commit(ObjRecord *orp);
144 static int obj_uppercase; /* Flag: all names in uppercase */
147 * Clear an ObjRecord structure. (Never reallocates).
148 * To simplify reuse of ObjRecord's, .type, .ori and .parm are not cleared.
150 static ObjRecord *obj_clear(ObjRecord *orp)
152 orp->used = 0;
153 orp->committed = 0;
154 orp->x_size = 0;
155 orp->child = NULL;
156 orp->up = NULL;
157 orp->back = NULL;
158 return (orp);
162 * Emit an ObjRecord structure. (Never reallocates).
163 * The record is written out preceeded (recursively) by its previous part (if
164 * any) and followed (recursively) by its child (if any).
165 * The previous part and the child are freed. The main ObjRecord is cleared,
166 * not freed.
168 static ObjRecord *obj_emit(ObjRecord *orp)
170 if (orp->back) {
171 obj_emit(orp->back);
172 nasm_free(orp->back);
175 if (orp->committed)
176 obj_fwrite(orp);
178 if (orp->child) {
179 obj_emit(orp->child);
180 nasm_free(orp->child);
183 return (obj_clear(orp));
187 * Commit and Emit a record. (Never reallocates).
189 static ObjRecord *obj_emit2(ObjRecord *orp)
191 obj_commit(orp);
192 return (obj_emit(orp));
196 * Allocate and clear a new ObjRecord; Also sets .ori to ori_null
198 static ObjRecord *obj_new(void)
200 ObjRecord *orp;
202 orp = obj_clear( nasm_malloc(sizeof(ObjRecord)) );
203 orp->ori = ori_null;
204 return (orp);
208 * Advance to the next record because the existing one is full or its x_size
209 * is incompatible.
210 * Any uncommited data is moved into the next record.
212 static ObjRecord *obj_bump(ObjRecord *orp)
214 ObjRecord *nxt;
215 int used = orp->used;
216 int committed = orp->committed;
218 if (orp->up) {
219 *orp->up = nxt = obj_new();
220 nxt->ori = orp->ori;
221 nxt->type = orp->type;
222 nxt->up = orp->up;
223 nxt->back = orp;
224 memcpy( nxt->parm, orp->parm, sizeof(orp->parm));
225 } else
226 nxt = obj_emit(orp);
228 used -= committed;
229 if (used) {
230 nxt->committed = 1;
231 nxt->ori (nxt);
232 nxt->committed = nxt->used;
233 memcpy( nxt->buf + nxt->committed, orp->buf + committed, used);
234 nxt->used = nxt->committed + used;
237 return (nxt);
241 * Advance to the next record if necessary to allow the next field to fit.
243 static ObjRecord *obj_check(ObjRecord *orp, int size)
245 if (orp->used + size > RECORD_MAX)
246 orp = obj_bump(orp);
248 if (!orp->committed) {
249 orp->committed = 1;
250 orp->ori (orp);
251 orp->committed = orp->used;
254 return (orp);
258 * All data written so far is commited to the current record (won't be moved to
259 * the next record in case of continuation).
261 static ObjRecord *obj_commit(ObjRecord *orp)
263 orp->committed = orp->used;
264 return (orp);
268 * Write a byte
270 static ObjRecord *obj_byte(ObjRecord *orp, unsigned char val)
272 orp = obj_check(orp, 1);
273 orp->buf[orp->used] = val;
274 orp->used++;
275 return (orp);
279 * Write a word
281 static ObjRecord *obj_word(ObjRecord *orp, unsigned int val)
283 orp = obj_check(orp, 2);
284 orp->buf[orp->used] = val;
285 orp->buf[orp->used+1] = val >> 8;
286 orp->used += 2;
287 return (orp);
291 * Write a reversed word
293 static ObjRecord *obj_rword(ObjRecord *orp, unsigned int val)
295 orp = obj_check(orp, 2);
296 orp->buf[orp->used] = val >> 8;
297 orp->buf[orp->used+1] = val;
298 orp->used += 2;
299 return (orp);
303 * Write a dword
305 static ObjRecord *obj_dword(ObjRecord *orp, unsigned long val)
307 orp = obj_check(orp, 4);
308 orp->buf[orp->used] = val;
309 orp->buf[orp->used+1] = val >> 8;
310 orp->buf[orp->used+2] = val >> 16;
311 orp->buf[orp->used+3] = val >> 24;
312 orp->used += 4;
313 return (orp);
317 * All fields of "size x" in one obj record must be the same size (either 16
318 * bits or 32 bits). There is a one bit flag in each record which specifies
319 * which.
320 * This routine is used to force the current record to have the desired
321 * x_size. x_size is normally automatic (using obj_x), so that this
322 * routine should be used outside obj_x, only to provide compatibility with
323 * linkers that have bugs in their processing of the size bit.
326 static ObjRecord *obj_force(ObjRecord *orp, int x)
328 if (orp->x_size == (x^48))
329 orp = obj_bump(orp);
330 orp->x_size = x;
331 return (orp);
335 * This routine writes a field of size x. The caller does not need to worry at
336 * all about whether 16-bits or 32-bits are required.
338 static ObjRecord *obj_x(ObjRecord *orp, unsigned long val)
340 if (orp->type & 1)
341 orp->x_size = 32;
342 if (val > 0xFFFF)
343 orp = obj_force(orp, 32);
344 if (orp->x_size == 32)
345 return (obj_dword(orp, val));
346 orp->x_size = 16;
347 return (obj_word(orp, val));
351 * Writes an index
353 static ObjRecord *obj_index(ObjRecord *orp, unsigned int val)
355 if (val < 128)
356 return ( obj_byte(orp, val) );
357 return (obj_word(orp, (val>>8) | (val<<8) | 0x80));
361 * Writes a variable length value
363 static ObjRecord *obj_value(ObjRecord *orp, unsigned long val)
365 if (val <= 128)
366 return ( obj_byte(orp, val) );
367 if (val <= 0xFFFF) {
368 orp = obj_byte(orp, 129);
369 return ( obj_word(orp, val) );
371 if (val <= 0xFFFFFF)
372 return ( obj_dword(orp, (val<<8) + 132 ) );
373 orp = obj_byte(orp, 136);
374 return ( obj_dword(orp, val) );
378 * Writes a counted string
380 static ObjRecord *obj_name(ObjRecord *orp, char *name)
382 int len = strlen(name);
383 unsigned char *ptr;
385 orp = obj_check(orp, len+1);
386 ptr = orp->buf + orp->used;
387 *ptr++ = len;
388 orp->used += len+1;
389 if (obj_uppercase)
390 while (--len >= 0) {
391 *ptr++ = toupper(*name);
392 name++;
393 } else
394 memcpy(ptr, name, len);
395 return (orp);
399 * Initializer for an LEDATA record.
400 * parm[0] = offset
401 * parm[1] = segment index
402 * During the use of a LEDATA ObjRecord, parm[0] is constantly updated to
403 * represent the offset that would be required if the record were split at the
404 * last commit point.
405 * parm[2] is a copy of parm[0] as it was when the current record was initted.
407 static void ori_ledata(ObjRecord *orp)
409 obj_index (orp, orp->parm[1]);
410 orp->parm[2] = orp->parm[0];
411 obj_x (orp, orp->parm[0]);
415 * Initializer for a PUBDEF record.
416 * parm[0] = group index
417 * parm[1] = segment index
418 * parm[2] = frame (only used when both indexes are zero)
420 static void ori_pubdef(ObjRecord *orp)
422 obj_index (orp, orp->parm[0]);
423 obj_index (orp, orp->parm[1]);
424 if ( !(orp->parm[0] | orp->parm[1]) )
425 obj_word (orp, orp->parm[2]);
429 * Initializer for a LINNUM record.
430 * parm[0] = group index
431 * parm[1] = segment index
433 static void ori_linnum(ObjRecord *orp)
435 obj_index (orp, orp->parm[0]);
436 obj_index (orp, orp->parm[1]);
439 * Initializer for a local vars record.
441 static void ori_local(ObjRecord *orp)
443 obj_byte (orp, 0x40);
444 obj_byte (orp, dSYM);
448 * Null initializer for records that continue without any header info
450 static void ori_null(ObjRecord *orp)
452 (void) orp; /* Do nothing */
456 * This concludes the low level section of outobj.c
459 static char obj_infile[FILENAME_MAX];
461 static efunc error;
462 static evalfunc evaluate;
463 static ldfunc deflabel;
464 static FILE *ofp;
465 static long first_seg;
466 static int any_segs;
467 static int passtwo;
468 static int arrindex;
470 #define GROUP_MAX 256 /* we won't _realistically_ have more
471 * than this many segs in a group */
472 #define EXT_BLKSIZ 256 /* block size for externals list */
474 struct Segment; /* need to know these structs exist */
475 struct Group;
477 struct LineNumber {
478 struct LineNumber *next;
479 struct Segment *segment;
480 long offset;
481 long lineno;
484 static struct FileName {
485 struct FileName *next;
486 char *name;
487 struct LineNumber *lnhead, **lntail;
488 int index;
489 } *fnhead, **fntail;
491 static struct Array {
492 struct Array *next;
493 unsigned size;
494 int basetype;
495 } *arrhead, **arrtail;
497 #define ARRAYBOT 31 /* magic number for first array index */
500 static struct Public {
501 struct Public *next;
502 char *name;
503 long offset;
504 long segment; /* only if it's far-absolute */
505 int type; /* only for local debug syms */
506 } *fpubhead, **fpubtail, *last_defined;
508 static struct External {
509 struct External *next;
510 char *name;
511 long commonsize;
512 long commonelem; /* element size if FAR, else zero */
513 int index; /* OBJ-file external index */
514 enum {
515 DEFWRT_NONE, /* no unusual default-WRT */
516 DEFWRT_STRING, /* a string we don't yet understand */
517 DEFWRT_SEGMENT, /* a segment */
518 DEFWRT_GROUP /* a group */
519 } defwrt_type;
520 union {
521 char *string;
522 struct Segment *seg;
523 struct Group *grp;
524 } defwrt_ptr;
525 struct External *next_dws; /* next with DEFWRT_STRING */
526 } *exthead, **exttail, *dws;
528 static int externals;
530 static struct ExtBack {
531 struct ExtBack *next;
532 struct External *exts[EXT_BLKSIZ];
533 } *ebhead, **ebtail;
535 static struct Segment {
536 struct Segment *next;
537 long index; /* the NASM segment id */
538 long obj_index; /* the OBJ-file segment index */
539 struct Group *grp; /* the group it belongs to */
540 unsigned long currentpos;
541 long align; /* can be SEG_ABS + absolute addr */
542 enum {
543 CMB_PRIVATE = 0,
544 CMB_PUBLIC = 2,
545 CMB_STACK = 5,
546 CMB_COMMON = 6
547 } combine;
548 long use32; /* is this segment 32-bit? */
549 struct Public *pubhead, **pubtail, *lochead, **loctail;
550 char *name;
551 char *segclass, *overlay; /* `class' is a C++ keyword :-) */
552 ObjRecord *orp;
553 } *seghead, **segtail, *obj_seg_needs_update;
555 static struct Group {
556 struct Group *next;
557 char *name;
558 long index; /* NASM segment id */
559 long obj_index; /* OBJ-file group index */
560 long nentries; /* number of elements... */
561 long nindices; /* ...and number of index elts... */
562 union {
563 long index;
564 char *name;
565 } segs[GROUP_MAX]; /* ...in this */
566 } *grphead, **grptail, *obj_grp_needs_update;
568 static struct ImpDef {
569 struct ImpDef *next;
570 char *extname;
571 char *libname;
572 unsigned int impindex;
573 char *impname;
574 } *imphead, **imptail;
576 static struct ExpDef {
577 struct ExpDef *next;
578 char *intname;
579 char *extname;
580 unsigned int ordinal;
581 int flags;
582 } *exphead, **exptail;
584 #define EXPDEF_FLAG_ORDINAL 0x80
585 #define EXPDEF_FLAG_RESIDENT 0x40
586 #define EXPDEF_FLAG_NODATA 0x20
587 #define EXPDEF_MASK_PARMCNT 0x1F
589 static long obj_entry_seg, obj_entry_ofs;
591 struct ofmt of_obj;
593 static long obj_segment (char *, int, int *);
594 static void obj_write_file(int debuginfo);
595 static int obj_directive (char *, char *, int);
597 static void obj_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
599 ofp = fp;
600 error = errfunc;
601 evaluate = eval;
602 deflabel = ldef;
603 first_seg = seg_alloc();
604 any_segs = FALSE;
605 fpubhead = NULL;
606 fpubtail = &fpubhead;
607 exthead = NULL;
608 exttail = &exthead;
609 imphead = NULL;
610 imptail = &imphead;
611 exphead = NULL;
612 exptail = &exphead;
613 dws = NULL;
614 externals = 0;
615 ebhead = NULL;
616 ebtail = &ebhead;
617 seghead = obj_seg_needs_update = NULL;
618 segtail = &seghead;
619 grphead = obj_grp_needs_update = NULL;
620 grptail = &grphead;
621 obj_entry_seg = NO_SEG;
622 obj_uppercase = FALSE;
623 passtwo = 0;
625 of_obj.current_dfmt->init (&of_obj,NULL,fp,errfunc);
628 static int obj_set_info(enum geninfo type, char **val)
630 (void) type;
631 (void) val;
633 return 0;
635 static void obj_cleanup (int debuginfo)
637 obj_write_file(debuginfo);
638 of_obj.current_dfmt->cleanup();
639 fclose (ofp);
640 while (seghead) {
641 struct Segment *segtmp = seghead;
642 seghead = seghead->next;
643 while (segtmp->pubhead) {
644 struct Public *pubtmp = segtmp->pubhead;
645 segtmp->pubhead = pubtmp->next;
646 nasm_free (pubtmp->name);
647 nasm_free (pubtmp);
649 nasm_free (segtmp->segclass);
650 nasm_free (segtmp->overlay);
651 nasm_free (segtmp);
653 while (fpubhead) {
654 struct Public *pubtmp = fpubhead;
655 fpubhead = fpubhead->next;
656 nasm_free (pubtmp->name);
657 nasm_free (pubtmp);
659 while (exthead) {
660 struct External *exttmp = exthead;
661 exthead = exthead->next;
662 nasm_free (exttmp);
664 while (imphead) {
665 struct ImpDef *imptmp = imphead;
666 imphead = imphead->next;
667 nasm_free (imptmp->extname);
668 nasm_free (imptmp->libname);
669 nasm_free (imptmp->impname); /* nasm_free won't mind if it's NULL */
670 nasm_free (imptmp);
672 while (exphead) {
673 struct ExpDef *exptmp = exphead;
674 exphead = exphead->next;
675 nasm_free (exptmp->extname);
676 nasm_free (exptmp->intname);
677 nasm_free (exptmp);
679 while (ebhead) {
680 struct ExtBack *ebtmp = ebhead;
681 ebhead = ebhead->next;
682 nasm_free (ebtmp);
684 while (grphead) {
685 struct Group *grptmp = grphead;
686 grphead = grphead->next;
687 nasm_free (grptmp);
691 static void obj_ext_set_defwrt (struct External *ext, char *id)
693 struct Segment *seg;
694 struct Group *grp;
696 for (seg = seghead; seg; seg = seg->next)
697 if (!strcmp(seg->name, id)) {
698 ext->defwrt_type = DEFWRT_SEGMENT;
699 ext->defwrt_ptr.seg = seg;
700 nasm_free (id);
701 return;
704 for (grp = grphead; grp; grp = grp->next)
705 if (!strcmp(grp->name, id)) {
706 ext->defwrt_type = DEFWRT_GROUP;
707 ext->defwrt_ptr.grp = grp;
708 nasm_free (id);
709 return;
712 ext->defwrt_type = DEFWRT_STRING;
713 ext->defwrt_ptr.string = id;
714 ext->next_dws = dws;
715 dws = ext;
718 static void obj_deflabel (char *name, long segment,
719 long offset, int is_global, char *special)
722 * We have three cases:
724 * (i) `segment' is a segment-base. If so, set the name field
725 * for the segment or group structure it refers to, and then
726 * return.
728 * (ii) `segment' is one of our segments, or a SEG_ABS segment.
729 * Save the label position for later output of a PUBDEF record.
730 * (Or a MODPUB, if we work out how.)
732 * (iii) `segment' is not one of our segments. Save the label
733 * position for later output of an EXTDEF, and also store a
734 * back-reference so that we can map later references to this
735 * segment number to the external index.
737 struct External *ext;
738 struct ExtBack *eb;
739 struct Segment *seg;
740 int i;
741 int used_special = FALSE; /* have we used the special text? */
744 * If it's a special-retry from pass two, discard it.
746 if (is_global == 3)
747 return;
750 * First check for the double-period, signifying something
751 * unusual.
753 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
754 if (!strcmp(name, "..start")) {
755 obj_entry_seg = segment;
756 obj_entry_ofs = offset;
757 return;
759 error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
763 * Case (i):
765 if (obj_seg_needs_update) {
766 obj_seg_needs_update->name = name;
767 return;
768 } else if (obj_grp_needs_update) {
769 obj_grp_needs_update->name = name;
770 return;
772 if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
773 return;
775 if (segment >= SEG_ABS || segment == NO_SEG) {
777 * SEG_ABS subcase of (ii).
779 if (is_global) {
780 struct Public *pub;
782 pub = *fpubtail = nasm_malloc(sizeof(*pub));
783 fpubtail = &pub->next;
784 pub->next = NULL;
785 pub->name = nasm_strdup(name);
786 pub->offset = offset;
787 pub->segment = (segment == NO_SEG ? 0 : segment & ~SEG_ABS);
789 if (special)
790 error(ERR_NONFATAL, "OBJ supports no special symbol features"
791 " for this symbol type");
792 return;
796 * If `any_segs' is still FALSE, we might need to define a
797 * default segment, if they're trying to declare a label in
798 * `first_seg'.
800 if (!any_segs && segment == first_seg) {
801 int tempint; /* ignored */
802 if (segment != obj_segment("__NASMDEFSEG", 2, &tempint))
803 error (ERR_PANIC, "strange segment conditions in OBJ driver");
806 for (seg = seghead; seg && is_global; seg = seg->next)
807 if (seg->index == segment) {
808 struct Public *loc = nasm_malloc (sizeof(*loc));
810 * Case (ii). Maybe MODPUB someday?
812 *seg->pubtail = loc;
813 seg->pubtail = &loc->next;
814 loc->next = NULL;
815 loc->name = nasm_strdup(name);
816 loc->offset = offset;
818 if (special)
819 error(ERR_NONFATAL, "OBJ supports no special symbol features"
820 " for this symbol type");
821 return;
825 * Case (iii).
827 if (is_global) {
828 ext = *exttail = nasm_malloc(sizeof(*ext));
829 ext->next = NULL;
830 exttail = &ext->next;
831 ext->name = name;
832 ext->defwrt_type = DEFWRT_NONE;
833 if (is_global == 2) {
834 ext->commonsize = offset;
835 ext->commonelem = 1; /* default FAR */
836 } else
837 ext->commonsize = 0;
839 else
840 return;
843 * Now process the special text, if any, to find default-WRT
844 * specifications and common-variable element-size and near/far
845 * specifications.
847 while (special && *special) {
848 used_special = TRUE;
851 * We might have a default-WRT specification.
853 if (!nasm_strnicmp(special, "wrt", 3)) {
854 char *p;
855 int len;
856 special += 3;
857 special += strspn(special, " \t");
858 p = nasm_strndup(special, len = strcspn(special, ":"));
859 obj_ext_set_defwrt (ext, p);
860 special += len;
861 if (*special && *special != ':')
862 error(ERR_NONFATAL, "`:' expected in special symbol"
863 " text for `%s'", ext->name);
864 else if (*special == ':')
865 special++;
869 * The NEAR or FAR keywords specify nearness or
870 * farness. FAR gives default element size 1.
872 if (!nasm_strnicmp(special, "far", 3)) {
873 if (ext->commonsize)
874 ext->commonelem = 1;
875 else
876 error(ERR_NONFATAL, "`%s': `far' keyword may only be applied"
877 " to common variables\n", ext->name);
878 special += 3;
879 special += strspn(special, " \t");
880 } else if (!nasm_strnicmp(special, "near", 4)) {
881 if (ext->commonsize)
882 ext->commonelem = 0;
883 else
884 error(ERR_NONFATAL, "`%s': `far' keyword may only be applied"
885 " to common variables\n", ext->name);
886 special += 4;
887 special += strspn(special, " \t");
891 * If it's a common, and anything else remains on the line
892 * before a further colon, evaluate it as an expression and
893 * use that as the element size. Forward references aren't
894 * allowed.
896 if (*special == ':')
897 special++;
898 else if (*special) {
899 if (ext->commonsize) {
900 expr *e;
901 struct tokenval tokval;
903 stdscan_reset();
904 stdscan_bufptr = special;
905 tokval.t_type = TOKEN_INVALID;
906 e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
907 if (e) {
908 if (!is_simple(e))
909 error (ERR_NONFATAL, "cannot use relocatable"
910 " expression as common-variable element size");
911 else
912 ext->commonelem = reloc_value(e);
914 special = stdscan_bufptr;
915 } else {
916 error (ERR_NONFATAL, "`%s': element-size specifications only"
917 " apply to common variables", ext->name);
918 while (*special && *special != ':')
919 special++;
920 if (*special == ':')
921 special++;
926 i = segment/2;
927 eb = ebhead;
928 if (!eb) {
929 eb = *ebtail = nasm_malloc(sizeof(*eb));
930 eb->next = NULL;
931 ebtail = &eb->next;
933 while (i > EXT_BLKSIZ) {
934 if (eb && eb->next)
935 eb = eb->next;
936 else {
937 eb = *ebtail = nasm_malloc(sizeof(*eb));
938 eb->next = NULL;
939 ebtail = &eb->next;
941 i -= EXT_BLKSIZ;
943 eb->exts[i] = ext;
944 ext->index = ++externals;
946 if (special && !used_special)
947 error(ERR_NONFATAL, "OBJ supports no special symbol features"
948 " for this symbol type");
951 /* forward declaration */
952 static void obj_write_fixup (ObjRecord *orp, int bytes,
953 int segrel, long seg, long wrt, struct Segment *segto);
955 static void obj_out (long segto, void *data, unsigned long type,
956 long segment, long wrt)
958 long size, realtype;
959 unsigned char *ucdata;
960 long ldata;
961 struct Segment *seg;
962 ObjRecord *orp;
965 * handle absolute-assembly (structure definitions)
967 if (segto == NO_SEG) {
968 if ((type & OUT_TYPMASK) != OUT_RESERVE)
969 error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
970 " space");
971 return;
975 * If `any_segs' is still FALSE, we must define a default
976 * segment.
978 if (!any_segs) {
979 int tempint; /* ignored */
980 if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
981 error (ERR_PANIC, "strange segment conditions in OBJ driver");
985 * Find the segment we are targetting.
987 for (seg = seghead; seg; seg = seg->next)
988 if (seg->index == segto)
989 break;
990 if (!seg)
991 error (ERR_PANIC, "code directed to nonexistent segment?");
993 orp = seg->orp;
994 orp->parm[0] = seg->currentpos;
996 size = type & OUT_SIZMASK;
997 realtype = type & OUT_TYPMASK;
998 if (realtype == OUT_RAWDATA) {
999 ucdata = data;
1000 while (size > 0) {
1001 unsigned int len;
1002 orp = obj_check(seg->orp, 1);
1003 len = RECORD_MAX - orp->used;
1004 if (len > size)
1005 len = size;
1006 memcpy (orp->buf+orp->used, ucdata, len);
1007 orp->committed = orp->used += len;
1008 orp->parm[0] = seg->currentpos += len;
1009 ucdata += len;
1010 size -= len;
1013 else if (realtype == OUT_ADDRESS || realtype == OUT_REL2ADR ||
1014 realtype == OUT_REL4ADR)
1016 int rsize;
1018 if (segment == NO_SEG && realtype != OUT_ADDRESS)
1019 error(ERR_NONFATAL, "relative call to absolute address not"
1020 " supported by OBJ format");
1021 if (segment >= SEG_ABS)
1022 error(ERR_NONFATAL, "far-absolute relocations not supported"
1023 " by OBJ format");
1024 ldata = *(long *)data;
1025 if (realtype == OUT_REL2ADR) {
1026 ldata += (size-2);
1027 size = 2;
1029 if (realtype == OUT_REL4ADR) {
1030 ldata += (size-4);
1031 size = 4;
1033 if (size == 2)
1034 orp = obj_word (orp, ldata);
1035 else
1036 orp = obj_dword (orp, ldata);
1037 rsize = size;
1038 if (segment < SEG_ABS && (segment != NO_SEG && segment % 2) &&
1039 size == 4) {
1041 * This is a 4-byte segment-base relocation such as
1042 * `MOV EAX,SEG foo'. OBJ format can't actually handle
1043 * these, but if the constant term has the 16 low bits
1044 * zero, we can just apply a 2-byte segment-base
1045 * relocation to the low word instead.
1047 rsize = 2;
1048 if (ldata & 0xFFFF)
1049 error(ERR_NONFATAL, "OBJ format cannot handle complex"
1050 " dword-size segment base references");
1052 if (segment != NO_SEG)
1053 obj_write_fixup (orp, rsize,
1054 (realtype == OUT_ADDRESS ? 0x4000 : 0),
1055 segment, wrt, seg);
1056 seg->currentpos += size;
1057 } else if (realtype == OUT_RESERVE) {
1058 if (orp->committed)
1059 orp = obj_bump(orp);
1060 seg->currentpos += size;
1062 obj_commit(orp);
1065 static void obj_write_fixup (ObjRecord *orp, int bytes,
1066 int segrel, long seg, long wrt, struct Segment *segto)
1068 int locat, method;
1069 int base;
1070 long tidx, fidx;
1071 struct Segment *s = NULL;
1072 struct Group *g = NULL;
1073 struct External *e = NULL;
1074 ObjRecord *forp;
1076 if (bytes == 1) {
1077 error(ERR_NONFATAL, "`obj' output driver does not support"
1078 " one-byte relocations");
1079 return;
1082 forp = orp->child;
1083 if (forp == NULL) {
1084 orp->child = forp = obj_new();
1085 forp->up = &(orp->child);
1086 /* We should choose between FIXUPP and FIXU32 record type */
1087 /* If we're targeting a 32-bit segment, use a FIXU32 record */
1088 if (segto->use32)
1089 forp->type = FIXU32;
1090 else
1091 forp->type = FIXUPP;
1094 if (seg % 2) {
1095 base = TRUE;
1096 locat = FIX_16_SELECTOR;
1097 seg--;
1098 if (bytes != 2)
1099 error(ERR_PANIC, "OBJ: 4-byte segment base fixup got"
1100 " through sanity check");
1102 else {
1103 base = FALSE;
1104 locat = (bytes == 2) ? FIX_16_OFFSET : FIX_32_OFFSET;
1105 if (!segrel)
1107 * There is a bug in tlink that makes it process self relative
1108 * fixups incorrectly if the x_size doesn't match the location
1109 * size.
1111 forp = obj_force(forp, bytes<<3);
1114 forp = obj_rword (forp, locat | segrel | (orp->parm[0]-orp->parm[2]));
1116 tidx = fidx = -1, method = 0; /* placate optimisers */
1119 * See if we can find the segment ID in our segment list. If
1120 * so, we have a T4 (LSEG) target.
1122 for (s = seghead; s; s = s->next)
1123 if (s->index == seg)
1124 break;
1125 if (s)
1126 method = 4, tidx = s->obj_index;
1127 else {
1128 for (g = grphead; g; g = g->next)
1129 if (g->index == seg)
1130 break;
1131 if (g)
1132 method = 5, tidx = g->obj_index;
1133 else {
1134 long i = seg/2;
1135 struct ExtBack *eb = ebhead;
1136 while (i > EXT_BLKSIZ) {
1137 if (eb)
1138 eb = eb->next;
1139 else
1140 break;
1141 i -= EXT_BLKSIZ;
1143 if (eb)
1144 method = 6, e = eb->exts[i], tidx = e->index;
1145 else
1146 error(ERR_PANIC,
1147 "unrecognised segment value in obj_write_fixup");
1152 * If no WRT given, assume the natural default, which is method
1153 * F5 unless:
1155 * - we are doing an OFFSET fixup for a grouped segment, in
1156 * which case we require F1 (group).
1158 * - we are doing an OFFSET fixup for an external with a
1159 * default WRT, in which case we must honour the default WRT.
1161 if (wrt == NO_SEG) {
1162 if (!base && s && s->grp)
1163 method |= 0x10, fidx = s->grp->obj_index;
1164 else if (!base && e && e->defwrt_type != DEFWRT_NONE) {
1165 if (e->defwrt_type == DEFWRT_SEGMENT)
1166 method |= 0x00, fidx = e->defwrt_ptr.seg->obj_index;
1167 else if (e->defwrt_type == DEFWRT_GROUP)
1168 method |= 0x10, fidx = e->defwrt_ptr.grp->obj_index;
1169 else {
1170 error(ERR_NONFATAL, "default WRT specification for"
1171 " external `%s' unresolved", e->name);
1172 method |= 0x50, fidx = -1; /* got to do _something_ */
1174 } else
1175 method |= 0x50, fidx = -1;
1176 } else {
1178 * See if we can find the WRT-segment ID in our segment
1179 * list. If so, we have a F0 (LSEG) frame.
1181 for (s = seghead; s; s = s->next)
1182 if (s->index == wrt-1)
1183 break;
1184 if (s)
1185 method |= 0x00, fidx = s->obj_index;
1186 else {
1187 for (g = grphead; g; g = g->next)
1188 if (g->index == wrt-1)
1189 break;
1190 if (g)
1191 method |= 0x10, fidx = g->obj_index;
1192 else {
1193 long i = wrt/2;
1194 struct ExtBack *eb = ebhead;
1195 while (i > EXT_BLKSIZ) {
1196 if (eb)
1197 eb = eb->next;
1198 else
1199 break;
1200 i -= EXT_BLKSIZ;
1202 if (eb)
1203 method |= 0x20, fidx = eb->exts[i]->index;
1204 else
1205 error(ERR_PANIC,
1206 "unrecognised WRT value in obj_write_fixup");
1211 forp = obj_byte (forp, method);
1212 if (fidx != -1)
1213 forp = obj_index (forp, fidx);
1214 forp = obj_index (forp, tidx);
1215 obj_commit (forp);
1218 static long obj_segment (char *name, int pass, int *bits)
1221 * We call the label manager here to define a name for the new
1222 * segment, and when our _own_ label-definition stub gets
1223 * called in return, it should register the new segment name
1224 * using the pointer it gets passed. That way we save memory,
1225 * by sponging off the label manager.
1227 if (!name) {
1228 *bits = 16;
1229 return first_seg;
1230 } else {
1231 struct Segment *seg;
1232 struct Group *grp;
1233 struct External **extp;
1234 int obj_idx, i, attrs, rn_error;
1235 char *p;
1238 * Look for segment attributes.
1240 attrs = 0;
1241 while (*name == '.')
1242 name++; /* hack, but a documented one */
1243 p = name;
1244 while (*p && !isspace(*p))
1245 p++;
1246 if (*p) {
1247 *p++ = '\0';
1248 while (*p && isspace(*p))
1249 *p++ = '\0';
1251 while (*p) {
1252 while (*p && !isspace(*p))
1253 p++;
1254 if (*p) {
1255 *p++ = '\0';
1256 while (*p && isspace(*p))
1257 *p++ = '\0';
1260 attrs++;
1263 obj_idx = 1;
1264 for (seg = seghead; seg; seg = seg->next) {
1265 obj_idx++;
1266 if (!strcmp(seg->name, name)) {
1267 if (attrs > 0 && pass == 1)
1268 error(ERR_WARNING, "segment attributes specified on"
1269 " redeclaration of segment: ignoring");
1270 if (seg->use32)
1271 *bits = 32;
1272 else
1273 *bits = 16;
1274 return seg->index;
1278 *segtail = seg = nasm_malloc(sizeof(*seg));
1279 seg->next = NULL;
1280 segtail = &seg->next;
1281 seg->index = (any_segs ? seg_alloc() : first_seg);
1282 seg->obj_index = obj_idx;
1283 seg->grp = NULL;
1284 any_segs = TRUE;
1285 seg->name = NULL;
1286 seg->currentpos = 0;
1287 seg->align = 1; /* default */
1288 seg->use32 = FALSE; /* default */
1289 seg->combine = CMB_PUBLIC; /* default */
1290 seg->segclass = seg->overlay = NULL;
1291 seg->pubhead = NULL;
1292 seg->pubtail = &seg->pubhead;
1293 seg->lochead = NULL;
1294 seg->loctail = &seg->lochead;
1295 seg->orp = obj_new();
1296 seg->orp->up = &(seg->orp);
1297 seg->orp->ori = ori_ledata;
1298 seg->orp->type = LEDATA;
1299 seg->orp->parm[1] = obj_idx;
1302 * Process the segment attributes.
1304 p = name;
1305 while (attrs--) {
1306 p += strlen(p);
1307 while (!*p) p++;
1310 * `p' contains a segment attribute.
1312 if (!nasm_stricmp(p, "private"))
1313 seg->combine = CMB_PRIVATE;
1314 else if (!nasm_stricmp(p, "public"))
1315 seg->combine = CMB_PUBLIC;
1316 else if (!nasm_stricmp(p, "common"))
1317 seg->combine = CMB_COMMON;
1318 else if (!nasm_stricmp(p, "stack"))
1319 seg->combine = CMB_STACK;
1320 else if (!nasm_stricmp(p, "use16"))
1321 seg->use32 = FALSE;
1322 else if (!nasm_stricmp(p, "use32"))
1323 seg->use32 = TRUE;
1324 else if (!nasm_stricmp(p, "flat")) {
1326 * This segment is an OS/2 FLAT segment. That means
1327 * that its default group is group FLAT, even if
1328 * the group FLAT does not explicitly _contain_ the
1329 * segment.
1331 * When we see this, we must create the group
1332 * `FLAT', containing no segments, if it does not
1333 * already exist; then we must set the default
1334 * group of this segment to be the FLAT group.
1336 struct Group *grp;
1337 for (grp = grphead; grp; grp = grp->next)
1338 if (!strcmp(grp->name, "FLAT"))
1339 break;
1340 if (!grp) {
1341 obj_directive ("group", "FLAT", 1);
1342 for (grp = grphead; grp; grp = grp->next)
1343 if (!strcmp(grp->name, "FLAT"))
1344 break;
1345 if (!grp)
1346 error (ERR_PANIC, "failure to define FLAT?!");
1348 seg->grp = grp;
1349 } else if (!nasm_strnicmp(p, "class=", 6))
1350 seg->segclass = nasm_strdup(p+6);
1351 else if (!nasm_strnicmp(p, "overlay=", 8))
1352 seg->overlay = nasm_strdup(p+8);
1353 else if (!nasm_strnicmp(p, "align=", 6)) {
1354 seg->align = readnum(p+6, &rn_error);
1355 if (rn_error) {
1356 seg->align = 1;
1357 error (ERR_NONFATAL, "segment alignment should be"
1358 " numeric");
1360 switch ((int) seg->align) {
1361 case 1: /* BYTE */
1362 case 2: /* WORD */
1363 case 4: /* DWORD */
1364 case 16: /* PARA */
1365 case 256: /* PAGE */
1366 case 4096: /* PharLap extension */
1367 break;
1368 case 8:
1369 error(ERR_WARNING, "OBJ format does not support alignment"
1370 " of 8: rounding up to 16");
1371 seg->align = 16;
1372 break;
1373 case 32:
1374 case 64:
1375 case 128:
1376 error(ERR_WARNING, "OBJ format does not support alignment"
1377 " of %d: rounding up to 256", seg->align);
1378 seg->align = 256;
1379 break;
1380 case 512:
1381 case 1024:
1382 case 2048:
1383 error(ERR_WARNING, "OBJ format does not support alignment"
1384 " of %d: rounding up to 4096", seg->align);
1385 seg->align = 4096;
1386 break;
1387 default:
1388 error(ERR_NONFATAL, "invalid alignment value %d",
1389 seg->align);
1390 seg->align = 1;
1391 break;
1393 } else if (!nasm_strnicmp(p, "absolute=", 9)) {
1394 seg->align = SEG_ABS + readnum(p+9, &rn_error);
1395 if (rn_error)
1396 error (ERR_NONFATAL, "argument to `absolute' segment"
1397 " attribute should be numeric");
1401 obj_seg_needs_update = seg;
1402 if (seg->align >= SEG_ABS)
1403 deflabel (name, NO_SEG, seg->align - SEG_ABS,
1404 NULL, FALSE, FALSE, &of_obj, error);
1405 else
1406 deflabel (name, seg->index+1, 0L,
1407 NULL, FALSE, FALSE, &of_obj, error);
1408 obj_seg_needs_update = NULL;
1411 * See if this segment is defined in any groups.
1413 for (grp = grphead; grp; grp = grp->next) {
1414 for (i = grp->nindices; i < grp->nentries; i++) {
1415 if (!strcmp(grp->segs[i].name, seg->name)) {
1416 nasm_free (grp->segs[i].name);
1417 grp->segs[i] = grp->segs[grp->nindices];
1418 grp->segs[grp->nindices++].index = seg->obj_index;
1419 if (seg->grp)
1420 error(ERR_WARNING, "segment `%s' is already part of"
1421 " a group: first one takes precedence",
1422 seg->name);
1423 else
1424 seg->grp = grp;
1430 * Walk through the list of externals with unresolved
1431 * default-WRT clauses, and resolve any that point at this
1432 * segment.
1434 extp = &dws;
1435 while (*extp) {
1436 if ((*extp)->defwrt_type == DEFWRT_STRING &&
1437 !strcmp((*extp)->defwrt_ptr.string, seg->name)) {
1438 nasm_free((*extp)->defwrt_ptr.string);
1439 (*extp)->defwrt_type = DEFWRT_SEGMENT;
1440 (*extp)->defwrt_ptr.seg = seg;
1441 *extp = (*extp)->next_dws;
1442 } else
1443 extp = &(*extp)->next_dws;
1446 if (seg->use32)
1447 *bits = 32;
1448 else
1449 *bits = 16;
1450 return seg->index;
1454 static int obj_directive (char *directive, char *value, int pass)
1456 if (!strcmp(directive, "group")) {
1457 char *p, *q, *v;
1458 if (pass == 1) {
1459 struct Group *grp;
1460 struct Segment *seg;
1461 struct External **extp;
1462 int obj_idx;
1464 q = value;
1465 while (*q == '.')
1466 q++; /* hack, but a documented one */
1467 v = q;
1468 while (*q && !isspace(*q))
1469 q++;
1470 if (isspace(*q)) {
1471 *q++ = '\0';
1472 while (*q && isspace(*q))
1473 q++;
1476 * Here we used to sanity-check the group directive to
1477 * ensure nobody tried to declare a group containing no
1478 * segments. However, OS/2 does this as standard
1479 * practice, so the sanity check has been removed.
1481 * if (!*q) {
1482 * error(ERR_NONFATAL,"GROUP directive contains no segments");
1483 * return 1;
1487 obj_idx = 1;
1488 for (grp = grphead; grp; grp = grp->next) {
1489 obj_idx++;
1490 if (!strcmp(grp->name, v)) {
1491 error(ERR_NONFATAL, "group `%s' defined twice", v);
1492 return 1;
1496 *grptail = grp = nasm_malloc(sizeof(*grp));
1497 grp->next = NULL;
1498 grptail = &grp->next;
1499 grp->index = seg_alloc();
1500 grp->obj_index = obj_idx;
1501 grp->nindices = grp->nentries = 0;
1502 grp->name = NULL;
1504 obj_grp_needs_update = grp;
1505 deflabel (v, grp->index+1, 0L,
1506 NULL, FALSE, FALSE, &of_obj, error);
1507 obj_grp_needs_update = NULL;
1509 while (*q) {
1510 p = q;
1511 while (*q && !isspace(*q))
1512 q++;
1513 if (isspace(*q)) {
1514 *q++ = '\0';
1515 while (*q && isspace(*q))
1516 q++;
1519 * Now p contains a segment name. Find it.
1521 for (seg = seghead; seg; seg = seg->next)
1522 if (!strcmp(seg->name, p))
1523 break;
1524 if (seg) {
1526 * We have a segment index. Shift a name entry
1527 * to the end of the array to make room.
1529 grp->segs[grp->nentries++] = grp->segs[grp->nindices];
1530 grp->segs[grp->nindices++].index = seg->obj_index;
1531 if (seg->grp)
1532 error(ERR_WARNING, "segment `%s' is already part of"
1533 " a group: first one takes precedence",
1534 seg->name);
1535 else
1536 seg->grp = grp;
1537 } else {
1539 * We have an as-yet undefined segment.
1540 * Remember its name, for later.
1542 grp->segs[grp->nentries++].name = nasm_strdup(p);
1547 * Walk through the list of externals with unresolved
1548 * default-WRT clauses, and resolve any that point at
1549 * this group.
1551 extp = &dws;
1552 while (*extp) {
1553 if ((*extp)->defwrt_type == DEFWRT_STRING &&
1554 !strcmp((*extp)->defwrt_ptr.string, grp->name)) {
1555 nasm_free((*extp)->defwrt_ptr.string);
1556 (*extp)->defwrt_type = DEFWRT_GROUP;
1557 (*extp)->defwrt_ptr.grp = grp;
1558 *extp = (*extp)->next_dws;
1559 } else
1560 extp = &(*extp)->next_dws;
1563 return 1;
1565 if (!strcmp(directive, "uppercase")) {
1566 obj_uppercase = TRUE;
1567 return 1;
1569 if (!strcmp(directive, "import")) {
1570 char *q, *extname, *libname, *impname;
1572 if (pass == 2)
1573 return 1; /* ignore in pass two */
1574 extname = q = value;
1575 while (*q && !isspace(*q))
1576 q++;
1577 if (isspace(*q)) {
1578 *q++ = '\0';
1579 while (*q && isspace(*q))
1580 q++;
1583 libname = q;
1584 while (*q && !isspace(*q))
1585 q++;
1586 if (isspace(*q)) {
1587 *q++ = '\0';
1588 while (*q && isspace(*q))
1589 q++;
1592 impname = q;
1594 if (!*extname || !*libname)
1595 error(ERR_NONFATAL, "`import' directive requires symbol name"
1596 " and library name");
1597 else {
1598 struct ImpDef *imp;
1599 int err = FALSE;
1601 imp = *imptail = nasm_malloc(sizeof(struct ImpDef));
1602 imptail = &imp->next;
1603 imp->next = NULL;
1604 imp->extname = nasm_strdup(extname);
1605 imp->libname = nasm_strdup(libname);
1606 imp->impindex = readnum(impname, &err);
1607 if (!*impname || err)
1608 imp->impname = nasm_strdup(impname);
1609 else
1610 imp->impname = NULL;
1613 return 1;
1615 if (!strcmp(directive, "export")) {
1616 char *q, *extname, *intname, *v;
1617 struct ExpDef *export;
1618 int flags = 0;
1619 unsigned int ordinal = 0;
1621 if (pass == 2)
1622 return 1; /* ignore in pass two */
1623 intname = q = value;
1624 while (*q && !isspace(*q))
1625 q++;
1626 if (isspace(*q)) {
1627 *q++ = '\0';
1628 while (*q && isspace(*q))
1629 q++;
1632 extname = q;
1633 while (*q && !isspace(*q))
1634 q++;
1635 if (isspace(*q)) {
1636 *q++ = '\0';
1637 while (*q && isspace(*q))
1638 q++;
1641 if (!*intname) {
1642 error(ERR_NONFATAL, "`export' directive requires export name");
1643 return 1;
1645 if (!*extname) {
1646 extname = intname;
1647 intname = "";
1649 while (*q) {
1650 v = q;
1651 while (*q && !isspace(*q))
1652 q++;
1653 if (isspace(*q)) {
1654 *q++ = '\0';
1655 while (*q && isspace(*q))
1656 q++;
1658 if (!nasm_stricmp(v, "resident"))
1659 flags |= EXPDEF_FLAG_RESIDENT;
1660 else if (!nasm_stricmp(v, "nodata"))
1661 flags |= EXPDEF_FLAG_NODATA;
1662 else if (!nasm_strnicmp(v, "parm=", 5)) {
1663 int err = FALSE;
1664 flags |= EXPDEF_MASK_PARMCNT & readnum(v+5, &err);
1665 if (err) {
1666 error(ERR_NONFATAL,
1667 "value `%s' for `parm' is non-numeric", v+5);
1668 return 1;
1670 } else {
1671 int err = FALSE;
1672 ordinal = readnum(v, &err);
1673 if (err) {
1674 error(ERR_NONFATAL, "unrecognised export qualifier `%s'",
1676 return 1;
1678 flags |= EXPDEF_FLAG_ORDINAL;
1682 export = *exptail = nasm_malloc(sizeof(struct ExpDef));
1683 exptail = &export->next;
1684 export->next = NULL;
1685 export->extname = nasm_strdup(extname);
1686 export->intname = nasm_strdup(intname);
1687 export->ordinal = ordinal;
1688 export->flags = flags;
1690 return 1;
1692 return 0;
1695 static long obj_segbase (long segment)
1697 struct Segment *seg;
1700 * Find the segment in our list.
1702 for (seg = seghead; seg; seg = seg->next)
1703 if (seg->index == segment-1)
1704 break;
1706 if (!seg) {
1708 * Might be an external with a default WRT.
1710 long i = segment/2;
1711 struct ExtBack *eb = ebhead;
1712 struct External *e;
1714 while (i > EXT_BLKSIZ) {
1715 if (eb)
1716 eb = eb->next;
1717 else
1718 break;
1719 i -= EXT_BLKSIZ;
1721 if (eb) {
1722 e = eb->exts[i];
1723 if (e->defwrt_type == DEFWRT_NONE)
1724 return segment; /* fine */
1725 else if (e->defwrt_type == DEFWRT_SEGMENT)
1726 return e->defwrt_ptr.seg->index+1;
1727 else if (e->defwrt_type == DEFWRT_GROUP)
1728 return e->defwrt_ptr.grp->index+1;
1729 else
1730 return NO_SEG; /* can't tell what it is */
1733 return segment; /* not one of ours - leave it alone */
1736 if (seg->align >= SEG_ABS)
1737 return seg->align; /* absolute segment */
1738 if (seg->grp)
1739 return seg->grp->index+1; /* grouped segment */
1741 return segment; /* no special treatment */
1744 static void obj_filename (char *inname, char *outname, efunc error)
1746 strcpy(obj_infile, inname);
1747 standard_extension (inname, outname, ".obj", error);
1750 static void obj_write_file (int debuginfo)
1752 struct Segment *seg, *entry_seg_ptr = 0;
1753 struct FileName *fn;
1754 struct LineNumber *ln;
1755 struct Group *grp;
1756 struct Public *pub, *loc;
1757 struct External *ext;
1758 struct ImpDef *imp;
1759 struct ExpDef *export;
1760 static char boast[] = "The Netwide Assembler " NASM_VER;
1761 int lname_idx;
1762 ObjRecord *orp;
1765 * Write the THEADR module header.
1767 orp = obj_new();
1768 orp->type = THEADR;
1769 obj_name (orp, obj_infile);
1770 obj_emit2 (orp);
1773 * Write the NASM boast comment.
1775 orp->type = COMENT;
1776 obj_rword (orp, 0); /* comment type zero */
1777 obj_name (orp, boast);
1778 obj_emit2 (orp);
1780 orp->type = COMENT;
1782 * Write the IMPDEF records, if any.
1784 for (imp = imphead; imp; imp = imp->next) {
1785 obj_rword (orp, 0xA0); /* comment class A0 */
1786 obj_byte (orp, 1); /* subfunction 1: IMPDEF */
1787 if (imp->impname)
1788 obj_byte (orp, 0); /* import by name */
1789 else
1790 obj_byte (orp, 1); /* import by ordinal */
1791 obj_name (orp, imp->extname);
1792 obj_name (orp, imp->libname);
1793 if (imp->impname)
1794 obj_name (orp, imp->impname);
1795 else
1796 obj_word (orp, imp->impindex);
1797 obj_emit2 (orp);
1801 * Write the EXPDEF records, if any.
1803 for (export = exphead; export; export = export->next) {
1804 obj_rword (orp, 0xA0); /* comment class A0 */
1805 obj_byte (orp, 2); /* subfunction 2: EXPDEF */
1806 obj_byte (orp, export->flags);
1807 obj_name (orp, export->extname);
1808 obj_name (orp, export->intname);
1809 if (export->flags & EXPDEF_FLAG_ORDINAL)
1810 obj_word (orp, export->ordinal);
1811 obj_emit2 (orp);
1814 /* we're using extended OMF if we put in debug info*/
1815 if (debuginfo) {
1816 orp->type = COMENT;
1817 obj_byte (orp, 0x40);
1818 obj_byte (orp, dEXTENDED);
1819 obj_emit2 (orp);
1823 * Write the first LNAMES record, containing LNAME one, which
1824 * is null. Also initialise the LNAME counter.
1826 orp->type = LNAMES;
1827 obj_byte (orp, 0);
1828 lname_idx = 1;
1830 * Write some LNAMES for the segment names
1832 for (seg = seghead; seg; seg = seg->next) {
1833 orp = obj_name (orp, seg->name);
1834 if (seg->segclass)
1835 orp = obj_name (orp, seg->segclass);
1836 if (seg->overlay)
1837 orp = obj_name (orp, seg->overlay);
1838 obj_commit (orp);
1841 * Write some LNAMES for the group names
1843 for (grp = grphead; grp; grp = grp->next) {
1844 orp = obj_name (orp, grp->name);
1845 obj_commit (orp);
1847 obj_emit (orp);
1851 * Write the SEGDEF records.
1853 orp->type = SEGDEF;
1854 for (seg = seghead; seg; seg = seg->next) {
1855 int acbp;
1856 unsigned long seglen = seg->currentpos;
1858 acbp = (seg->combine << 2); /* C field */
1860 if (seg->use32)
1861 acbp |= 0x01; /* P bit is Use32 flag */
1862 else if (seglen == 0x10000L) {
1863 seglen = 0; /* This special case may be needed for old linkers */
1864 acbp |= 0x02; /* B bit */
1868 /* A field */
1869 if (seg->align >= SEG_ABS)
1870 /* acbp |= 0x00 */;
1871 else if (seg->align >= 4096) {
1872 if (seg->align > 4096)
1873 error(ERR_NONFATAL, "segment `%s' requires more alignment"
1874 " than OBJ format supports", seg->name);
1875 acbp |= 0xC0; /* PharLap extension */
1876 } else if (seg->align >= 256) {
1877 acbp |= 0x80;
1878 } else if (seg->align >= 16) {
1879 acbp |= 0x60;
1880 } else if (seg->align >= 4) {
1881 acbp |= 0xA0;
1882 } else if (seg->align >= 2) {
1883 acbp |= 0x40;
1884 } else
1885 acbp |= 0x20;
1887 obj_byte (orp, acbp);
1888 if (seg->align & SEG_ABS) {
1889 obj_x (orp, seg->align - SEG_ABS); /* Frame */
1890 obj_byte (orp, 0); /* Offset */
1892 obj_x (orp, seglen);
1893 obj_index (orp, ++lname_idx);
1894 obj_index (orp, seg->segclass ? ++lname_idx : 1);
1895 obj_index (orp, seg->overlay ? ++lname_idx : 1);
1896 obj_emit2 (orp);
1900 * Write the GRPDEF records.
1902 orp->type = GRPDEF;
1903 for (grp = grphead; grp; grp = grp->next) {
1904 int i;
1906 if (grp->nindices != grp->nentries) {
1907 for (i = grp->nindices; i < grp->nentries; i++) {
1908 error(ERR_NONFATAL, "group `%s' contains undefined segment"
1909 " `%s'", grp->name, grp->segs[i].name);
1910 nasm_free (grp->segs[i].name);
1911 grp->segs[i].name = NULL;
1914 obj_index (orp, ++lname_idx);
1915 for (i = 0; i < grp->nindices; i++) {
1916 obj_byte (orp, 0xFF);
1917 obj_index (orp, grp->segs[i].index);
1919 obj_emit2 (orp);
1923 * Write the PUBDEF records: first the ones in the segments,
1924 * then the far-absolutes.
1926 orp->type = PUBDEF;
1927 orp->ori = ori_pubdef;
1928 for (seg = seghead; seg; seg = seg->next) {
1929 orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
1930 orp->parm[1] = seg->obj_index;
1931 for (pub = seg->pubhead; pub; pub = pub->next) {
1932 orp = obj_name (orp, pub->name);
1933 orp = obj_x (orp, pub->offset);
1934 orp = obj_byte (orp, 0); /* type index */
1935 obj_commit (orp);
1937 obj_emit (orp);
1939 orp->parm[0] = 0;
1940 orp->parm[1] = 0;
1941 for (pub = fpubhead; pub; pub = pub->next) { /* pub-crawl :-) */
1942 if (orp->parm[2] != pub->segment) {
1943 obj_emit (orp);
1944 orp->parm[2] = pub->segment;
1946 orp = obj_name (orp, pub->name);
1947 orp = obj_x (orp, pub->offset);
1948 orp = obj_byte (orp, 0); /* type index */
1949 obj_commit (orp);
1951 obj_emit (orp);
1954 * Write the EXTDEF and COMDEF records, in order.
1956 orp->ori = ori_null;
1957 for (ext = exthead; ext; ext = ext->next) {
1958 if (ext->commonsize == 0) {
1959 if (orp->type != EXTDEF) {
1960 obj_emit (orp);
1961 orp->type = EXTDEF;
1963 orp = obj_name (orp, ext->name);
1964 orp = obj_index (orp, 0);
1965 } else {
1966 if (orp->type != COMDEF) {
1967 obj_emit (orp);
1968 orp->type = COMDEF;
1970 orp = obj_name (orp, ext->name);
1971 orp = obj_index (orp, 0);
1972 if (ext->commonelem) {
1973 orp = obj_byte (orp, 0x61);/* far communal */
1974 orp = obj_value (orp, (ext->commonsize / ext->commonelem));
1975 orp = obj_value (orp, ext->commonelem);
1976 } else {
1977 orp = obj_byte (orp, 0x62);/* near communal */
1978 orp = obj_value (orp, ext->commonsize);
1981 obj_commit (orp);
1983 obj_emit (orp);
1986 * Write a COMENT record stating that the linker's first pass
1987 * may stop processing at this point. Exception is if our
1988 * MODEND record specifies a start point, in which case,
1989 * according to some variants of the documentation, this COMENT
1990 * should be omitted. So we'll omit it just in case.
1991 * But, TASM puts it in all the time so if we are using
1992 * TASM debug stuff we are putting it in
1994 if (debuginfo || obj_entry_seg == NO_SEG) {
1995 orp->type = COMENT;
1996 obj_byte (orp, 0x40);
1997 obj_byte (orp, dLINKPASS);
1998 obj_byte (orp, 1);
1999 obj_emit2 (orp);
2003 * 1) put out the compiler type
2004 * 2) Put out the type info. The only type we are using is near label #19
2006 if (debuginfo) {
2007 int i;
2008 struct Array *arrtmp = arrhead;
2009 orp->type = COMENT;
2010 obj_byte (orp, 0x40);
2011 obj_byte (orp, dCOMPDEF);
2012 obj_byte (orp, 4);
2013 obj_byte (orp, 0);
2014 obj_emit2 (orp);
2016 obj_byte (orp, 0x40);
2017 obj_byte (orp, dTYPEDEF);
2018 obj_word (orp, 0x18); /* type # for linking */
2019 obj_word (orp, 6); /* size of type */
2020 obj_byte (orp, 0x2a); /* absolute type for debugging */
2021 obj_emit2 (orp);
2022 obj_byte (orp, 0x40);
2023 obj_byte (orp, dTYPEDEF);
2024 obj_word (orp, 0x19); /* type # for linking */
2025 obj_word (orp, 0); /* size of type */
2026 obj_byte (orp, 0x24); /* absolute type for debugging */
2027 obj_byte (orp, 0); /* near/far specifier */
2028 obj_emit2 (orp);
2029 obj_byte (orp, 0x40);
2030 obj_byte (orp, dTYPEDEF);
2031 obj_word (orp, 0x1A); /* type # for linking */
2032 obj_word (orp, 0); /* size of type */
2033 obj_byte (orp, 0x24); /* absolute type for debugging */
2034 obj_byte (orp, 1); /* near/far specifier */
2035 obj_emit2 (orp);
2036 obj_byte (orp, 0x40);
2037 obj_byte (orp, dTYPEDEF);
2038 obj_word (orp, 0x1b); /* type # for linking */
2039 obj_word (orp, 0); /* size of type */
2040 obj_byte (orp, 0x23); /* absolute type for debugging */
2041 obj_byte (orp, 0);
2042 obj_byte (orp, 0);
2043 obj_byte (orp, 0);
2044 obj_emit2 (orp);
2045 obj_byte (orp, 0x40);
2046 obj_byte (orp, dTYPEDEF);
2047 obj_word (orp, 0x1c); /* type # for linking */
2048 obj_word (orp, 0); /* size of type */
2049 obj_byte (orp, 0x23); /* absolute type for debugging */
2050 obj_byte (orp, 0);
2051 obj_byte (orp, 4);
2052 obj_byte (orp, 0);
2053 obj_emit2 (orp);
2054 obj_byte (orp, 0x40);
2055 obj_byte (orp, dTYPEDEF);
2056 obj_word (orp, 0x1d); /* type # for linking */
2057 obj_word (orp, 0); /* size of type */
2058 obj_byte (orp, 0x23); /* absolute type for debugging */
2059 obj_byte (orp, 0);
2060 obj_byte (orp, 1);
2061 obj_byte (orp, 0);
2062 obj_emit2 (orp);
2063 obj_byte (orp, 0x40);
2064 obj_byte (orp, dTYPEDEF);
2065 obj_word (orp, 0x1e); /* type # for linking */
2066 obj_word (orp, 0); /* size of type */
2067 obj_byte (orp, 0x23); /* absolute type for debugging */
2068 obj_byte (orp, 0);
2069 obj_byte (orp, 5);
2070 obj_byte (orp, 0);
2071 obj_emit2 (orp);
2073 /* put out the array types */
2074 for (i= ARRAYBOT; i < arrindex; i++) {
2075 obj_byte (orp, 0x40);
2076 obj_byte (orp, dTYPEDEF);
2077 obj_word (orp, i ); /* type # for linking */
2078 obj_word (orp, arrtmp->size); /* size of type */
2079 obj_byte (orp, 0x1A); /* absolute type for debugging (array)*/
2080 obj_byte (orp, arrtmp->basetype ); /* base type */
2081 obj_emit2 (orp);
2082 arrtmp = arrtmp->next ;
2086 * write out line number info with a LINNUM record
2087 * switch records when we switch segments, and output the
2088 * file in a pseudo-TASM fashion. The record switch is naive; that
2089 * is that one file may have many records for the same segment
2090 * if there are lots of segment switches
2092 if (fnhead && debuginfo) {
2093 seg = fnhead->lnhead->segment;
2095 for (fn = fnhead; fn; fn = fn->next) {
2096 /* write out current file name */
2097 orp->type = COMENT;
2098 orp->ori = ori_null;
2099 obj_byte (orp, 0x40);
2100 obj_byte (orp, dFILNAME);
2101 obj_byte( orp,0);
2102 obj_name( orp,fn->name);
2103 obj_dword(orp, 0);
2104 obj_emit2 (orp);
2106 /* write out line numbers this file */
2108 orp->type = LINNUM;
2109 orp->ori = ori_linnum;
2110 for (ln = fn->lnhead; ln; ln = ln->next) {
2111 if (seg != ln->segment) {
2112 /* if we get here have to flush the buffer and start
2113 * a new record for a new segment
2115 seg = ln->segment;
2116 obj_emit ( orp );
2118 orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
2119 orp->parm[1] = seg->obj_index;
2120 orp = obj_word(orp, ln->lineno);
2121 orp = obj_x(orp, ln->offset);
2122 obj_commit (orp);
2124 obj_emit (orp);
2128 * we are going to locate the entry point segment now
2129 * rather than wait until the MODEND record, because,
2130 * then we can output a special symbol to tell where the
2131 * entry point is.
2134 if (obj_entry_seg != NO_SEG) {
2135 for (seg = seghead; seg; seg = seg->next) {
2136 if (seg->index == obj_entry_seg) {
2137 entry_seg_ptr = seg;
2138 break;
2141 if (!seg)
2142 error(ERR_NONFATAL, "entry point is not in this module");
2146 * get ready to put out symbol records
2148 orp->type = COMENT;
2149 orp->ori = ori_local;
2152 * put out a symbol for the entry point
2153 * no dots in this symbol, because, borland does
2154 * not (officially) support dots in label names
2155 * and I don't know what various versions of TLINK will do
2157 if (debuginfo && obj_entry_seg != NO_SEG) {
2158 orp = obj_name (orp,"start_of_program");
2159 orp = obj_word (orp,0x19); /* type: near label */
2160 orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
2161 orp = obj_index (orp, seg->obj_index);
2162 orp = obj_x (orp, obj_entry_ofs);
2163 obj_commit (orp);
2167 * put out the local labels
2169 for (seg = seghead; seg && debuginfo; seg = seg->next) {
2170 /* labels this seg */
2171 for (loc = seg->lochead; loc; loc = loc->next) {
2172 orp = obj_name (orp,loc->name);
2173 orp = obj_word (orp, loc->type);
2174 orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
2175 orp = obj_index (orp, seg->obj_index);
2176 orp = obj_x (orp,loc->offset);
2177 obj_commit (orp);
2180 if (orp->used)
2181 obj_emit (orp);
2184 * Write the LEDATA/FIXUPP pairs.
2186 for (seg = seghead; seg; seg = seg->next) {
2187 obj_emit (seg->orp);
2188 nasm_free (seg->orp);
2192 * Write the MODEND module end marker.
2194 orp->type = MODEND;
2195 orp->ori = ori_null;
2196 if (entry_seg_ptr) {
2197 obj_byte (orp, 0xC1);
2198 seg = entry_seg_ptr;
2199 if (seg->grp) {
2200 obj_byte (orp, 0x10);
2201 obj_index (orp, seg->grp->obj_index);
2202 } else {
2204 * the below changed to prevent TLINK crashing.
2205 * Previous more efficient version read:
2207 * obj_byte (orp, 0x50);
2209 obj_byte (orp, 0x00);
2210 obj_index (orp, seg->obj_index);
2212 obj_index (orp, seg->obj_index);
2213 obj_x (orp, obj_entry_ofs);
2214 } else
2215 obj_byte (orp, 0);
2216 obj_emit2 (orp);
2217 nasm_free (orp);
2220 void obj_fwrite(ObjRecord *orp)
2222 unsigned int cksum, len;
2223 unsigned char *ptr;
2225 cksum = orp->type;
2226 if (orp->x_size == 32)
2227 cksum |= 1;
2228 fputc (cksum, ofp);
2229 len = orp->committed+1;
2230 cksum += (len & 0xFF) + ((len>>8) & 0xFF);
2231 fwriteshort (len, ofp);
2232 fwrite (orp->buf, 1, len-1, ofp);
2233 for (ptr=orp->buf; --len; ptr++)
2234 cksum += *ptr;
2235 fputc ( (-cksum) & 0xFF, ofp);
2238 static char *obj_stdmac[] = {
2239 "%define __SECT__ [section .text]",
2240 "%imacro group 1+.nolist",
2241 "[group %1]",
2242 "%endmacro",
2243 "%imacro uppercase 0+.nolist",
2244 "[uppercase %1]",
2245 "%endmacro",
2246 "%imacro export 1+.nolist",
2247 "[export %1]",
2248 "%endmacro",
2249 "%imacro import 1+.nolist",
2250 "[import %1]",
2251 "%endmacro",
2252 "%macro __NASM_CDecl__ 1",
2253 "%endmacro",
2254 NULL
2257 void dbgbi_init(struct ofmt * of, void * id, FILE * fp, efunc error)
2259 (void) of;
2260 (void) id;
2261 (void) fp;
2262 (void) error;
2264 fnhead = NULL;
2265 fntail = &fnhead;
2266 arrindex = ARRAYBOT ;
2267 arrhead = NULL;
2268 arrtail = &arrhead;
2270 static void dbgbi_cleanup(void)
2272 struct Segment *segtmp;
2273 while (fnhead) {
2274 struct FileName *fntemp = fnhead;
2275 while (fnhead->lnhead) {
2276 struct LineNumber *lntemp = fnhead->lnhead;
2277 fnhead->lnhead = lntemp->next;
2278 nasm_free( lntemp);
2280 fnhead = fnhead->next;
2281 nasm_free (fntemp->name);
2282 nasm_free (fntemp);
2284 for (segtmp=seghead; segtmp; segtmp=segtmp->next) {
2285 while (segtmp->lochead) {
2286 struct Public *loctmp = segtmp->lochead;
2287 segtmp->lochead = loctmp->next;
2288 nasm_free (loctmp->name);
2289 nasm_free (loctmp);
2292 while (arrhead) {
2293 struct Array *arrtmp = arrhead;
2294 arrhead = arrhead->next;
2295 nasm_free (arrtmp);
2299 static void dbgbi_linnum (const char *lnfname, long lineno, long segto)
2301 struct FileName *fn;
2302 struct LineNumber *ln;
2303 struct Segment *seg;
2305 if (segto == NO_SEG)
2306 return;
2309 * If `any_segs' is still FALSE, we must define a default
2310 * segment.
2312 if (!any_segs) {
2313 int tempint; /* ignored */
2314 if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
2315 error (ERR_PANIC, "strange segment conditions in OBJ driver");
2319 * Find the segment we are targetting.
2321 for (seg = seghead; seg; seg = seg->next)
2322 if (seg->index == segto)
2323 break;
2324 if (!seg)
2325 error (ERR_PANIC, "lineno directed to nonexistent segment?");
2327 for (fn = fnhead; fn; fn = fnhead->next)
2328 if (!nasm_stricmp(lnfname,fn->name))
2329 break;
2330 if (!fn) {
2331 fn = nasm_malloc ( sizeof( *fn));
2332 fn->name = nasm_malloc ( strlen(lnfname) + 1) ;
2333 strcpy (fn->name,lnfname);
2334 fn->lnhead = NULL;
2335 fn->lntail = & fn->lnhead;
2336 fn->next = NULL;
2337 *fntail = fn;
2338 fntail = &fn->next;
2340 ln = nasm_malloc ( sizeof( *ln));
2341 ln->segment = seg;
2342 ln->offset = seg->currentpos;
2343 ln->lineno = lineno;
2344 ln->next = NULL;
2345 *fn->lntail = ln;
2346 fn->lntail = &ln->next;
2349 static void dbgbi_deflabel (char *name, long segment,
2350 long offset, int is_global, char *special)
2352 struct Segment *seg;
2354 (void) special;
2357 * If it's a special-retry from pass two, discard it.
2359 if (is_global == 3)
2360 return;
2363 * First check for the double-period, signifying something
2364 * unusual.
2366 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
2367 return;
2371 * Case (i):
2373 if (obj_seg_needs_update) {
2374 return;
2375 } else if (obj_grp_needs_update) {
2376 return;
2378 if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
2379 return;
2381 if (segment >= SEG_ABS || segment == NO_SEG) {
2382 return;
2386 * If `any_segs' is still FALSE, we might need to define a
2387 * default segment, if they're trying to declare a label in
2388 * `first_seg'. But the label should exist due to a prior
2389 * call to obj_deflabel so we can skip that.
2392 for (seg = seghead; seg; seg = seg->next)
2393 if (seg->index == segment) {
2394 struct Public *loc = nasm_malloc (sizeof(*loc));
2396 * Case (ii). Maybe MODPUB someday?
2398 last_defined = *seg->loctail = loc;
2399 seg->loctail = &loc->next;
2400 loc->next = NULL;
2401 loc->name = nasm_strdup(name);
2402 loc->offset = offset;
2405 static void dbgbi_typevalue (long type)
2407 int vsize;
2408 int elem = TYM_ELEMENTS(type);
2409 type = TYM_TYPE(type);
2411 if (!last_defined)
2412 return;
2414 switch (type) {
2415 case TY_BYTE:
2416 last_defined->type = 8; /* unsigned char */
2417 vsize = 1;
2418 break;
2419 case TY_WORD:
2420 last_defined->type = 10; /* unsigned word */
2421 vsize = 2;
2422 break;
2423 case TY_DWORD:
2424 last_defined->type = 12; /* unsigned dword */
2425 vsize = 4;
2426 break;
2427 case TY_FLOAT:
2428 last_defined->type = 14; /* float */
2429 vsize = 4;
2430 break;
2431 case TY_QWORD:
2432 last_defined->type = 15; /* qword */
2433 vsize = 8;
2434 break;
2435 case TY_TBYTE:
2436 last_defined->type = 16; /* TBYTE */
2437 vsize = 10;
2438 break;
2439 default:
2440 last_defined->type = 0x19; /*label */
2441 vsize = 0;
2442 break;
2445 if (elem > 1) {
2446 struct Array *arrtmp = nasm_malloc (sizeof(*arrtmp));
2447 int vtype = last_defined->type;
2448 arrtmp->size = vsize * elem;
2449 arrtmp->basetype = vtype;
2450 arrtmp->next = NULL;
2451 last_defined->type = arrindex++;
2452 *arrtail = arrtmp;
2453 arrtail = & (arrtmp->next);
2455 last_defined = NULL;
2457 static void dbgbi_output (int output_type, void *param)
2459 (void) output_type;
2460 (void) param;
2462 static struct dfmt borland_debug_form = {
2463 "Borland Debug Records",
2464 "borland",
2465 dbgbi_init,
2466 dbgbi_linnum,
2467 dbgbi_deflabel,
2468 null_debug_routine,
2469 dbgbi_typevalue,
2470 dbgbi_output,
2471 dbgbi_cleanup,
2474 static struct dfmt *borland_debug_arr[3] = {
2475 &borland_debug_form,
2476 &null_debug_form,
2477 NULL
2480 struct ofmt of_obj = {
2481 "MS-DOS 16-bit/32-bit OMF object files",
2482 "obj",
2483 NULL,
2484 borland_debug_arr,
2485 &null_debug_form,
2486 obj_stdmac,
2487 obj_init,
2488 obj_set_info,
2489 obj_out,
2490 obj_deflabel,
2491 obj_segment,
2492 obj_segbase,
2493 obj_directive,
2494 obj_filename,
2495 obj_cleanup
2497 #endif /* OF_OBJ */