1 /* outobj.c output routines for the Netwide Assembler to produce
2 * Microsoft 16-bit .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.
21 static char obj_infile
[FILENAME_MAX
];
22 static int obj_uppercase
;
25 static evalfunc evaluate
;
26 static ldfunc deflabel
;
28 static long first_seg
;
31 #define LEDATA_MAX 1024 /* maximum size of LEDATA record */
32 #define RECORD_MAX 1024 /* maximum size of _any_ record */
33 #define GROUP_MAX 256 /* we won't _realistically_ have more
34 * than this many segs in a group */
35 #define EXT_BLKSIZ 256 /* block size for externals list */
37 static unsigned char record
[RECORD_MAX
], *recptr
;
39 struct Segment
; /* need to know these structs exist */
42 static struct Public
{
46 long segment
; /* only if it's far-absolute */
47 } *fpubhead
, **fpubtail
;
49 static struct External
{
50 struct External
*next
;
53 long commonelem
; /* element size if FAR, else zero */
54 int index
; /* OBJ-file external index */
56 DEFWRT_NONE
, /* no unusual default-WRT */
57 DEFWRT_STRING
, /* a string we don't yet understand */
58 DEFWRT_SEGMENT
, /* a segment */
59 DEFWRT_GROUP
/* a group */
66 struct External
*next_dws
; /* next with DEFWRT_STRING */
67 } *exthead
, **exttail
, *dws
;
71 static struct ExtBack
{
73 struct External
*exts
[EXT_BLKSIZ
];
76 static struct Segment
{
78 long index
; /* the NASM segment id */
79 long obj_index
; /* the OBJ-file segment index */
80 struct Group
*grp
; /* the group it belongs to */
82 long align
; /* can be SEG_ABS + absolute addr */
89 long use32
; /* is this segment 32-bit? */
90 struct Public
*pubhead
, **pubtail
;
92 char *segclass
, *overlay
; /* `class' is a C++ keyword :-) */
93 } *seghead
, **segtail
, *obj_seg_needs_update
;
98 long index
; /* NASM segment id */
99 long obj_index
; /* OBJ-file group index */
100 long nentries
; /* number of elements... */
101 long nindices
; /* ...and number of index elts... */
105 } segs
[GROUP_MAX
]; /* ...in this */
106 } *grphead
, **grptail
, *obj_grp_needs_update
;
108 static struct ObjData
{
109 struct ObjData
*next
;
114 unsigned char ledata
[LEDATA_MAX
], *lptr
;
115 unsigned char fixupp
[RECORD_MAX
], *fptr
;
116 } *datahead
, *datacurr
, **datatail
;
118 static struct ImpDef
{
122 unsigned int impindex
;
124 } *imphead
, **imptail
;
126 static struct ExpDef
{
130 unsigned int ordinal
;
132 } *exphead
, **exptail
;
134 #define EXPDEF_FLAG_ORDINAL 0x80
135 #define EXPDEF_FLAG_RESIDENT 0x40
136 #define EXPDEF_FLAG_NODATA 0x20
137 #define EXPDEF_MASK_PARMCNT 0x1F
139 static long obj_entry_seg
, obj_entry_ofs
;
141 enum RecordID
{ /* record ID codes */
143 THEADR
= 0x80, /* module header */
144 COMENT
= 0x88, /* comment record */
146 LNAMES
= 0x96, /* list of names */
148 SEGDEF
= 0x98, /* segment definition */
149 GRPDEF
= 0x9A, /* group definition */
150 EXTDEF
= 0x8C, /* external definition */
151 PUBDEF
= 0x90, /* public definition */
152 COMDEF
= 0xB0, /* common definition */
154 LEDATA
= 0xA0, /* logical enumerated data */
155 FIXUPP
= 0x9C, /* fixups (relocations) */
157 MODEND
= 0x8A /* module end */
160 extern struct ofmt of_obj
;
162 static long obj_ledata_space(struct Segment
*);
163 static int obj_fixup_free(struct Segment
*);
164 static void obj_ledata_new(struct Segment
*);
165 static void obj_ledata_commit(void);
166 static void obj_write_fixup (struct ObjData
*, int, int, long, long, long);
167 static long obj_segment (char *, int, int *);
168 static void obj_write_file(void);
169 static unsigned char *obj_write_data(unsigned char *, unsigned char *, int);
170 static unsigned char *obj_write_byte(unsigned char *, int);
171 static unsigned char *obj_write_word(unsigned char *, int);
172 static unsigned char *obj_write_dword(unsigned char *, long);
173 static unsigned char *obj_write_rword(unsigned char *, int);
174 static unsigned char *obj_write_name(unsigned char *, char *);
175 static unsigned char *obj_write_index(unsigned char *, int);
176 static unsigned char *obj_write_value(unsigned char *, unsigned long);
177 static void obj_record(int, unsigned char *, unsigned char *);
178 static int obj_directive (char *, char *, int);
180 static void obj_init (FILE *fp
, efunc errfunc
, ldfunc ldef
, evalfunc eval
) {
185 first_seg
= seg_alloc();
188 fpubtail
= &fpubhead
;
199 seghead
= obj_seg_needs_update
= NULL
;
201 grphead
= obj_grp_needs_update
= NULL
;
203 datahead
= datacurr
= NULL
;
204 datatail
= &datahead
;
205 obj_entry_seg
= NO_SEG
;
206 obj_uppercase
= FALSE
;
209 static void obj_cleanup (void) {
213 struct Segment
*segtmp
= seghead
;
214 seghead
= seghead
->next
;
215 while (segtmp
->pubhead
) {
216 struct Public
*pubtmp
= segtmp
->pubhead
;
217 segtmp
->pubhead
= pubtmp
->next
;
218 nasm_free (pubtmp
->name
);
224 struct Public
*pubtmp
= fpubhead
;
225 fpubhead
= fpubhead
->next
;
226 nasm_free (pubtmp
->name
);
230 struct External
*exttmp
= exthead
;
231 exthead
= exthead
->next
;
235 struct ImpDef
*imptmp
= imphead
;
236 imphead
= imphead
->next
;
237 nasm_free (imptmp
->extname
);
238 nasm_free (imptmp
->libname
);
239 nasm_free (imptmp
->impname
); /* nasm_free won't mind if it's NULL */
243 struct ExpDef
*exptmp
= exphead
;
244 exphead
= exphead
->next
;
245 nasm_free (exptmp
->extname
);
246 nasm_free (exptmp
->intname
);
250 struct ExtBack
*ebtmp
= ebhead
;
251 ebhead
= ebhead
->next
;
255 struct Group
*grptmp
= grphead
;
256 grphead
= grphead
->next
;
260 struct ObjData
*datatmp
= datahead
;
261 datahead
= datahead
->next
;
266 static void obj_ext_set_defwrt (struct External
*ext
, char *id
) {
270 for (seg
= seghead
; seg
; seg
= seg
->next
)
271 if (!strcmp(seg
->name
, id
)) {
272 ext
->defwrt_type
= DEFWRT_SEGMENT
;
273 ext
->defwrt_ptr
.seg
= seg
;
278 for (grp
= grphead
; grp
; grp
= grp
->next
)
279 if (!strcmp(grp
->name
, id
)) {
280 ext
->defwrt_type
= DEFWRT_GROUP
;
281 ext
->defwrt_ptr
.grp
= grp
;
286 ext
->defwrt_type
= DEFWRT_STRING
;
287 ext
->defwrt_ptr
.string
= id
;
292 static void obj_deflabel (char *name
, long segment
,
293 long offset
, int is_global
, char *special
) {
295 * We have three cases:
297 * (i) `segment' is a segment-base. If so, set the name field
298 * for the segment or group structure it refers to, and then
301 * (ii) `segment' is one of our segments, or a SEG_ABS segment.
302 * Save the label position for later output of a PUBDEF record.
303 * (Or a MODPUB, if we work out how.)
305 * (iii) `segment' is not one of our segments. Save the label
306 * position for later output of an EXTDEF, and also store a
307 * back-reference so that we can map later references to this
308 * segment number to the external index.
310 struct External
*ext
;
314 int used_special
= FALSE
; /* have we used the special text? */
317 * If it's a special-retry from pass two, discard it.
323 * First check for the double-period, signifying something
326 if (name
[0] == '.' && name
[1] == '.' && name
[2] != '@') {
327 if (!strcmp(name
, "..start")) {
328 obj_entry_seg
= segment
;
329 obj_entry_ofs
= offset
;
332 error (ERR_NONFATAL
, "unrecognised special symbol `%s'", name
);
338 if (obj_seg_needs_update
) {
339 obj_seg_needs_update
->name
= name
;
341 } else if (obj_grp_needs_update
) {
342 obj_grp_needs_update
->name
= name
;
345 if (segment
< SEG_ABS
&& segment
!= NO_SEG
&& segment
% 2)
348 if (segment
>= SEG_ABS
|| segment
== NO_SEG
) {
350 * SEG_ABS subcase of (ii).
355 pub
= *fpubtail
= nasm_malloc(sizeof(*pub
));
356 fpubtail
= &pub
->next
;
358 pub
->name
= nasm_strdup(name
);
359 pub
->offset
= offset
;
360 pub
->segment
= (segment
== NO_SEG
? 0 : segment
& ~SEG_ABS
);
363 error(ERR_NONFATAL
, "OBJ supports no special symbol features"
364 " for this symbol type");
369 * If `any_segs' is still FALSE, we might need to define a
370 * default segment, if they're trying to declare a label in
373 if (!any_segs
&& segment
== first_seg
) {
374 int tempint
; /* ignored */
375 if (segment
!= obj_segment("__NASMDEFSEG", 2, &tempint
))
376 error (ERR_PANIC
, "strange segment conditions in OBJ driver");
379 for (seg
= seghead
; seg
; seg
= seg
->next
)
380 if (seg
->index
== segment
) {
382 * Case (ii). Maybe MODPUB someday?
386 pub
= *seg
->pubtail
= nasm_malloc(sizeof(*pub
));
387 seg
->pubtail
= &pub
->next
;
389 pub
->name
= nasm_strdup(name
);
390 pub
->offset
= offset
;
393 error(ERR_NONFATAL
, "OBJ supports no special symbol features"
394 " for this symbol type");
401 ext
= *exttail
= nasm_malloc(sizeof(*ext
));
403 exttail
= &ext
->next
;
405 ext
->defwrt_type
= DEFWRT_NONE
;
406 if (is_global
== 2) {
407 ext
->commonsize
= offset
;
408 ext
->commonelem
= 1; /* default FAR */
413 * Now process the special text, if any, to find default-WRT
414 * specifications and common-variable element-size and near/far
417 while (special
&& *special
) {
421 * We might have a default-WRT specification.
423 if (!nasm_strnicmp(special
, "wrt", 3)) {
427 special
+= strspn(special
, " \t");
428 p
= nasm_strndup(special
, len
= strcspn(special
, ":"));
429 obj_ext_set_defwrt (ext
, p
);
431 if (*special
&& *special
!= ':')
432 error(ERR_NONFATAL
, "`:' expected in special symbol"
433 " text for `%s'", ext
->name
);
434 else if (*special
== ':')
439 * The NEAR or FAR keywords specify nearness or
440 * farness. FAR gives default element size 1.
442 if (!nasm_strnicmp(special
, "far", 3)) {
446 error(ERR_NONFATAL
, "`%s': `far' keyword may only be applied"
447 " to common variables\n", ext
->name
);
449 special
+= strspn(special
, " \t");
450 } else if (!nasm_strnicmp(special
, "near", 4)) {
454 error(ERR_NONFATAL
, "`%s': `far' keyword may only be applied"
455 " to common variables\n", ext
->name
);
457 special
+= strspn(special
, " \t");
461 * If it's a common, and anything else remains on the line
462 * before a further colon, evaluate it as an expression and
463 * use that as the element size. Forward references aren't
469 if (ext
->commonsize
) {
471 struct tokenval tokval
;
474 stdscan_bufptr
= special
;
475 tokval
.t_type
= TOKEN_INVALID
;
476 e
= evaluate(stdscan
, NULL
, &tokval
, NULL
, 1, error
, NULL
);
479 error (ERR_NONFATAL
, "cannot use relocatable"
480 " expression as common-variable element size");
482 ext
->commonelem
= reloc_value(e
);
484 special
= stdscan_bufptr
;
486 error (ERR_NONFATAL
, "`%s': element-size specifications only"
487 " apply to common variables", ext
->name
);
488 while (*special
&& *special
!= ':')
499 eb
= *ebtail
= nasm_malloc(sizeof(*eb
));
503 while (i
> EXT_BLKSIZ
) {
507 eb
= *ebtail
= nasm_malloc(sizeof(*eb
));
514 ext
->index
= ++externals
;
516 if (special
&& !used_special
)
517 error(ERR_NONFATAL
, "OBJ supports no special symbol features"
518 " for this symbol type");
521 static void obj_out (long segto
, void *data
, unsigned long type
,
522 long segment
, long wrt
) {
524 unsigned char *ucdata
;
529 * handle absolute-assembly (structure definitions)
531 if (segto
== NO_SEG
) {
532 if ((type
& OUT_TYPMASK
) != OUT_RESERVE
)
533 error (ERR_NONFATAL
, "attempt to assemble code in [ABSOLUTE]"
539 * If `any_segs' is still FALSE, we must define a default
543 int tempint
; /* ignored */
544 if (segto
!= obj_segment("__NASMDEFSEG", 2, &tempint
))
545 error (ERR_PANIC
, "strange segment conditions in OBJ driver");
549 * Find the segment we are targetting.
551 for (seg
= seghead
; seg
; seg
= seg
->next
)
552 if (seg
->index
== segto
)
555 error (ERR_PANIC
, "code directed to nonexistent segment?");
557 size
= type
& OUT_SIZMASK
;
558 realtype
= type
& OUT_TYPMASK
;
559 if (realtype
== OUT_RAWDATA
) {
562 long len
= obj_ledata_space(seg
);
565 len
= obj_ledata_space(seg
);
569 datacurr
->lptr
= obj_write_data (datacurr
->lptr
, ucdata
, len
);
570 datacurr
->nonempty
= TRUE
;
573 seg
->currentpos
+= len
;
575 } else if (realtype
== OUT_ADDRESS
|| realtype
== OUT_REL2ADR
||
576 realtype
== OUT_REL4ADR
) {
579 if (segment
== NO_SEG
&& realtype
!= OUT_ADDRESS
)
580 error(ERR_NONFATAL
, "relative call to absolute address not"
581 " supported by OBJ format");
582 if (segment
>= SEG_ABS
)
583 error(ERR_NONFATAL
, "far-absolute relocations not supported"
585 ldata
= *(long *)data
;
586 if (realtype
== OUT_REL2ADR
) {
590 if (realtype
== OUT_REL4ADR
) {
594 if (obj_ledata_space(seg
) < 4 || !obj_fixup_free(seg
))
597 datacurr
->lptr
= obj_write_word (datacurr
->lptr
, ldata
);
599 datacurr
->lptr
= obj_write_dword (datacurr
->lptr
, ldata
);
600 datacurr
->nonempty
= TRUE
;
602 if (segment
< SEG_ABS
&& (segment
!= NO_SEG
&& segment
% 2) &&
605 * This is a 4-byte segment-base relocation such as
606 * `MOV EAX,SEG foo'. OBJ format can't actually handle
607 * these, but if the constant term has the 16 low bits
608 * zero, we can just apply a 2-byte segment-base
609 * relocation to the low word instead.
613 error(ERR_NONFATAL
, "OBJ format cannot handle complex"
614 " dword-size segment base references");
616 if (segment
!= NO_SEG
)
617 obj_write_fixup (datacurr
, rsize
,
618 (realtype
== OUT_REL2ADR
||
619 realtype
== OUT_REL4ADR
? 0 : 0x4000),
621 (seg
->currentpos
- datacurr
->startpos
));
622 seg
->currentpos
+= size
;
623 } else if (realtype
== OUT_RESERVE
) {
625 seg
->currentpos
+= size
;
629 static long obj_ledata_space(struct Segment
*segto
) {
630 if (datacurr
&& datacurr
->seg
== segto
)
631 return datacurr
->ledata
+ LEDATA_MAX
- datacurr
->lptr
;
636 static int obj_fixup_free(struct Segment
*segto
) {
637 if (datacurr
&& datacurr
->seg
== segto
)
638 return (datacurr
->fixupp
+ RECORD_MAX
- datacurr
->fptr
) > 8;
643 static void obj_ledata_new(struct Segment
*segto
) {
644 datacurr
= *datatail
= nasm_malloc(sizeof(*datacurr
));
645 datacurr
->next
= NULL
;
646 datatail
= &datacurr
->next
;
647 datacurr
->nonempty
= FALSE
;
648 datacurr
->lptr
= datacurr
->ledata
;
649 datacurr
->fptr
= datacurr
->fixupp
;
650 datacurr
->seg
= segto
;
652 datacurr
->letype
= LEDATA
+1;
654 datacurr
->letype
= LEDATA
;
655 datacurr
->startpos
= segto
->currentpos
;
656 datacurr
->ftype
= FIXUPP
;
658 datacurr
->lptr
= obj_write_index (datacurr
->lptr
, segto
->obj_index
);
659 if (datacurr
->letype
== LEDATA
)
660 datacurr
->lptr
= obj_write_word (datacurr
->lptr
, segto
->currentpos
);
662 datacurr
->lptr
= obj_write_dword (datacurr
->lptr
, segto
->currentpos
);
665 static void obj_ledata_commit(void) {
669 static void obj_write_fixup (struct ObjData
*data
, int bytes
,
670 int segrel
, long seg
, long wrt
,
675 struct Segment
*s
= NULL
;
676 struct Group
*g
= NULL
;
677 struct External
*e
= NULL
;
680 error(ERR_NONFATAL
, "`obj' output driver does not support"
681 " one-byte relocations");
685 locat
= 0x8000 | segrel
| offset
;
691 error(ERR_PANIC
, "OBJ: 4-byte segment base fixup got"
692 " through sanity check");
699 data
->ftype
= FIXUPP
+1; /* need new-style FIXUPP record */
702 data
->fptr
= obj_write_rword (data
->fptr
, locat
);
704 tidx
= fidx
= -1, method
= 0; /* placate optimisers */
707 * See if we can find the segment ID in our segment list. If
708 * so, we have a T4 (LSEG) target.
710 for (s
= seghead
; s
; s
= s
->next
)
714 method
= 4, tidx
= s
->obj_index
;
716 for (g
= grphead
; g
; g
= g
->next
)
720 method
= 5, tidx
= g
->obj_index
;
723 struct ExtBack
*eb
= ebhead
;
724 while (i
> EXT_BLKSIZ
) {
732 method
= 6, e
= eb
->exts
[i
], tidx
= e
->index
;
735 "unrecognised segment value in obj_write_fixup");
740 * If no WRT given, assume the natural default, which is method
743 * - we are doing an OFFSET fixup for a grouped segment, in
744 * which case we require F1 (group).
746 * - we are doing an OFFSET fixup for an external with a
747 * default WRT, in which case we must honour the default WRT.
750 if (!base
&& s
&& s
->grp
)
751 method
|= 0x10, fidx
= s
->grp
->obj_index
;
752 else if (!base
&& e
&& e
->defwrt_type
!= DEFWRT_NONE
) {
753 if (e
->defwrt_type
== DEFWRT_SEGMENT
)
754 method
|= 0x00, fidx
= e
->defwrt_ptr
.seg
->obj_index
;
755 else if (e
->defwrt_type
== DEFWRT_GROUP
)
756 method
|= 0x10, fidx
= e
->defwrt_ptr
.grp
->obj_index
;
758 error(ERR_NONFATAL
, "default WRT specification for"
759 " external `%s' unresolved", e
->name
);
760 method
|= 0x50, fidx
= -1; /* got to do _something_ */
763 method
|= 0x50, fidx
= -1;
766 * See if we can find the WRT-segment ID in our segment
767 * list. If so, we have a F0 (LSEG) frame.
769 for (s
= seghead
; s
; s
= s
->next
)
770 if (s
->index
== wrt
-1)
773 method
|= 0x00, fidx
= s
->obj_index
;
775 for (g
= grphead
; g
; g
= g
->next
)
776 if (g
->index
== wrt
-1)
779 method
|= 0x10, fidx
= g
->obj_index
;
782 struct ExtBack
*eb
= ebhead
;
783 while (i
> EXT_BLKSIZ
) {
791 method
|= 0x20, fidx
= eb
->exts
[i
]->index
;
794 "unrecognised WRT value in obj_write_fixup");
799 data
->fptr
= obj_write_byte (data
->fptr
, method
);
801 data
->fptr
= obj_write_index (data
->fptr
, fidx
);
802 data
->fptr
= obj_write_index (data
->fptr
, tidx
);
805 static long obj_segment (char *name
, int pass
, int *bits
) {
807 * We call the label manager here to define a name for the new
808 * segment, and when our _own_ label-definition stub gets
809 * called in return, it should register the new segment name
810 * using the pointer it gets passed. That way we save memory,
811 * by sponging off the label manager.
819 struct External
**extp
;
820 int obj_idx
, i
, attrs
, rn_error
;
824 * Look for segment attributes.
828 name
++; /* hack, but a documented one */
830 while (*p
&& !isspace(*p
))
834 while (*p
&& isspace(*p
))
838 while (*p
&& !isspace(*p
))
842 while (*p
&& isspace(*p
))
850 for (seg
= seghead
; seg
; seg
= seg
->next
) {
852 if (!strcmp(seg
->name
, name
)) {
853 if (attrs
> 0 && pass
== 1)
854 error(ERR_WARNING
, "segment attributes specified on"
855 " redeclaration of segment: ignoring");
864 *segtail
= seg
= nasm_malloc(sizeof(*seg
));
866 segtail
= &seg
->next
;
867 seg
->index
= (any_segs
? seg_alloc() : first_seg
);
868 seg
->obj_index
= obj_idx
;
873 seg
->align
= 1; /* default */
874 seg
->use32
= FALSE
; /* default */
875 seg
->combine
= CMB_PUBLIC
; /* default */
876 seg
->segclass
= seg
->overlay
= NULL
;
878 seg
->pubtail
= &seg
->pubhead
;
881 * Process the segment attributes.
889 * `p' contains a segment attribute.
891 if (!nasm_stricmp(p
, "private"))
892 seg
->combine
= CMB_PRIVATE
;
893 else if (!nasm_stricmp(p
, "public"))
894 seg
->combine
= CMB_PUBLIC
;
895 else if (!nasm_stricmp(p
, "common"))
896 seg
->combine
= CMB_COMMON
;
897 else if (!nasm_stricmp(p
, "stack"))
898 seg
->combine
= CMB_STACK
;
899 else if (!nasm_stricmp(p
, "use16"))
901 else if (!nasm_stricmp(p
, "use32"))
903 else if (!nasm_stricmp(p
, "flat")) {
905 * This segment is an OS/2 FLAT segment. That means
906 * that its default group is group FLAT, even if
907 * the group FLAT does not explicitly _contain_ the
910 * When we see this, we must create the group
911 * `FLAT', containing no segments, if it does not
912 * already exist; then we must set the default
913 * group of this segment to be the FLAT group.
916 for (grp
= grphead
; grp
; grp
= grp
->next
)
917 if (!strcmp(grp
->name
, "FLAT"))
920 obj_directive ("group", "FLAT", 1);
921 for (grp
= grphead
; grp
; grp
= grp
->next
)
922 if (!strcmp(grp
->name
, "FLAT"))
925 error (ERR_PANIC
, "failure to define FLAT?!");
928 } else if (!nasm_strnicmp(p
, "class=", 6))
929 seg
->segclass
= nasm_strdup(p
+6);
930 else if (!nasm_strnicmp(p
, "overlay=", 8))
931 seg
->overlay
= nasm_strdup(p
+8);
932 else if (!nasm_strnicmp(p
, "align=", 6)) {
933 seg
->align
= readnum(p
+6, &rn_error
);
936 error (ERR_NONFATAL
, "segment alignment should be"
939 switch ((int) seg
->align
) {
945 case 4096: /* PharLap extension */
948 error(ERR_WARNING
, "OBJ format does not support alignment"
949 " of 8: rounding up to 16");
955 error(ERR_WARNING
, "OBJ format does not support alignment"
956 " of %d: rounding up to 256", seg
->align
);
962 error(ERR_WARNING
, "OBJ format does not support alignment"
963 " of %d: rounding up to 4096", seg
->align
);
967 error(ERR_NONFATAL
, "invalid alignment value %d",
972 } else if (!nasm_strnicmp(p
, "absolute=", 9)) {
973 seg
->align
= SEG_ABS
+ readnum(p
+9, &rn_error
);
975 error (ERR_NONFATAL
, "argument to `absolute' segment"
976 " attribute should be numeric");
980 obj_seg_needs_update
= seg
;
981 if (seg
->align
>= SEG_ABS
)
982 deflabel (name
, NO_SEG
, seg
->align
- SEG_ABS
,
983 NULL
, FALSE
, FALSE
, &of_obj
, error
);
985 deflabel (name
, seg
->index
+1, 0L,
986 NULL
, FALSE
, FALSE
, &of_obj
, error
);
987 obj_seg_needs_update
= NULL
;
990 * See if this segment is defined in any groups.
992 for (grp
= grphead
; grp
; grp
= grp
->next
) {
993 for (i
= grp
->nindices
; i
< grp
->nentries
; i
++) {
994 if (!strcmp(grp
->segs
[i
].name
, seg
->name
)) {
995 nasm_free (grp
->segs
[i
].name
);
996 grp
->segs
[i
] = grp
->segs
[grp
->nindices
];
997 grp
->segs
[grp
->nindices
++].index
= seg
->obj_index
;
999 error(ERR_WARNING
, "segment `%s' is already part of"
1000 " a group: first one takes precedence",
1009 * Walk through the list of externals with unresolved
1010 * default-WRT clauses, and resolve any that point at this
1015 if ((*extp
)->defwrt_type
== DEFWRT_STRING
&&
1016 !strcmp((*extp
)->defwrt_ptr
.string
, seg
->name
)) {
1017 (*extp
)->defwrt_type
= DEFWRT_SEGMENT
;
1018 (*extp
)->defwrt_ptr
.seg
= seg
;
1019 *extp
= (*extp
)->next_dws
;
1021 extp
= &(*extp
)->next_dws
;
1032 static int obj_directive (char *directive
, char *value
, int pass
) {
1033 if (!strcmp(directive
, "group")) {
1037 struct Segment
*seg
;
1038 struct External
**extp
;
1043 q
++; /* hack, but a documented one */
1045 while (*q
&& !isspace(*q
))
1049 while (*q
&& isspace(*q
))
1053 * Here we used to sanity-check the group directive to
1054 * ensure nobody tried to declare a group containing no
1055 * segments. However, OS/2 does this as standard
1056 * practice, so the sanity check has been removed.
1059 * error(ERR_NONFATAL,"GROUP directive contains no segments");
1065 for (grp
= grphead
; grp
; grp
= grp
->next
) {
1067 if (!strcmp(grp
->name
, v
)) {
1068 error(ERR_NONFATAL
, "group `%s' defined twice", v
);
1073 *grptail
= grp
= nasm_malloc(sizeof(*grp
));
1075 grptail
= &grp
->next
;
1076 grp
->index
= seg_alloc();
1077 grp
->obj_index
= obj_idx
;
1078 grp
->nindices
= grp
->nentries
= 0;
1081 obj_grp_needs_update
= grp
;
1082 deflabel (v
, grp
->index
+1, 0L,
1083 NULL
, FALSE
, FALSE
, &of_obj
, error
);
1084 obj_grp_needs_update
= NULL
;
1088 while (*q
&& !isspace(*q
))
1092 while (*q
&& isspace(*q
))
1096 * Now p contains a segment name. Find it.
1098 for (seg
= seghead
; seg
; seg
= seg
->next
)
1099 if (!strcmp(seg
->name
, p
))
1103 * We have a segment index. Shift a name entry
1104 * to the end of the array to make room.
1106 grp
->segs
[grp
->nentries
++] = grp
->segs
[grp
->nindices
];
1107 grp
->segs
[grp
->nindices
++].index
= seg
->obj_index
;
1109 error(ERR_WARNING
, "segment `%s' is already part of"
1110 " a group: first one takes precedence",
1116 * We have an as-yet undefined segment.
1117 * Remember its name, for later.
1119 grp
->segs
[grp
->nentries
++].name
= nasm_strdup(p
);
1124 * Walk through the list of externals with unresolved
1125 * default-WRT clauses, and resolve any that point at
1130 if ((*extp
)->defwrt_type
== DEFWRT_STRING
&&
1131 !strcmp((*extp
)->defwrt_ptr
.string
, grp
->name
)) {
1132 (*extp
)->defwrt_type
= DEFWRT_GROUP
;
1133 (*extp
)->defwrt_ptr
.grp
= grp
;
1134 *extp
= (*extp
)->next_dws
;
1136 extp
= &(*extp
)->next_dws
;
1141 if (!strcmp(directive
, "uppercase")) {
1142 obj_uppercase
= TRUE
;
1145 if (!strcmp(directive
, "import")) {
1146 char *q
, *extname
, *libname
, *impname
;
1149 return 1; /* ignore in pass two */
1150 extname
= q
= value
;
1151 while (*q
&& !isspace(*q
))
1155 while (*q
&& isspace(*q
))
1160 while (*q
&& !isspace(*q
))
1164 while (*q
&& isspace(*q
))
1170 if (!*extname
|| !*libname
)
1171 error(ERR_NONFATAL
, "`import' directive requires symbol name"
1172 " and library name");
1177 imp
= *imptail
= nasm_malloc(sizeof(struct ImpDef
));
1178 imptail
= &imp
->next
;
1180 imp
->extname
= nasm_strdup(extname
);
1181 imp
->libname
= nasm_strdup(libname
);
1182 imp
->impindex
= readnum(impname
, &err
);
1183 if (!*impname
|| err
)
1184 imp
->impname
= nasm_strdup(impname
);
1186 imp
->impname
= NULL
;
1191 if (!strcmp(directive
, "export")) {
1192 char *q
, *extname
, *intname
, *v
;
1193 struct ExpDef
*export
;
1195 unsigned int ordinal
= 0;
1198 return 1; /* ignore in pass two */
1199 intname
= q
= value
;
1200 while (*q
&& !isspace(*q
))
1204 while (*q
&& isspace(*q
))
1209 while (*q
&& !isspace(*q
))
1213 while (*q
&& isspace(*q
))
1218 error(ERR_NONFATAL
, "`export' directive requires export name");
1227 while (*q
&& !isspace(*q
))
1231 while (*q
&& isspace(*q
))
1234 if (!nasm_stricmp(v
, "resident"))
1235 flags
|= EXPDEF_FLAG_RESIDENT
;
1236 else if (!nasm_stricmp(v
, "nodata"))
1237 flags
|= EXPDEF_FLAG_NODATA
;
1238 else if (!nasm_strnicmp(v
, "parm=", 5)) {
1240 flags
|= EXPDEF_MASK_PARMCNT
& readnum(v
+5, &err
);
1243 "value `%s' for `parm' is non-numeric", v
+5);
1248 ordinal
= readnum(v
, &err
);
1250 error(ERR_NONFATAL
, "unrecognised export qualifier `%s'",
1254 flags
|= EXPDEF_FLAG_ORDINAL
;
1258 export
= *exptail
= nasm_malloc(sizeof(struct ExpDef
));
1259 exptail
= &export
->next
;
1260 export
->next
= NULL
;
1261 export
->extname
= nasm_strdup(extname
);
1262 export
->intname
= nasm_strdup(intname
);
1263 export
->ordinal
= ordinal
;
1264 export
->flags
= flags
;
1271 static long obj_segbase (long segment
) {
1272 struct Segment
*seg
;
1275 * Find the segment in our list.
1277 for (seg
= seghead
; seg
; seg
= seg
->next
)
1278 if (seg
->index
== segment
-1)
1283 * Might be an external with a default WRT.
1286 struct ExtBack
*eb
= ebhead
;
1289 while (i
> EXT_BLKSIZ
) {
1298 if (e
->defwrt_type
== DEFWRT_NONE
)
1299 return segment
; /* fine */
1300 else if (e
->defwrt_type
== DEFWRT_SEGMENT
)
1301 return e
->defwrt_ptr
.seg
->index
+1;
1302 else if (e
->defwrt_type
== DEFWRT_GROUP
)
1303 return e
->defwrt_ptr
.grp
->index
+1;
1304 else if (e
->defwrt_type
== DEFWRT_STRING
)
1305 return NO_SEG
; /* can't tell what it is */
1308 return segment
; /* not one of ours - leave it alone */
1311 if (seg
->align
>= SEG_ABS
)
1312 return seg
->align
; /* absolute segment */
1314 return seg
->grp
->index
+1; /* grouped segment */
1316 return segment
; /* no special treatment */
1319 static void obj_filename (char *inname
, char *outname
, efunc error
) {
1320 strcpy(obj_infile
, inname
);
1321 standard_extension (inname
, outname
, ".obj", error
);
1324 static void obj_write_file (void) {
1325 struct Segment
*seg
;
1328 struct External
*ext
;
1329 struct ObjData
*data
;
1331 struct ExpDef
*export
;
1332 static char boast
[] = "The Netwide Assembler " NASM_VER
;
1333 int lname_idx
, rectype
;
1336 * Write the THEADR module header.
1339 recptr
= obj_write_name (recptr
, obj_infile
);
1340 obj_record (THEADR
, record
, recptr
);
1343 * Write the NASM boast comment.
1346 recptr
= obj_write_rword (recptr
, 0); /* comment type zero */
1347 recptr
= obj_write_name (recptr
, boast
);
1348 obj_record (COMENT
, record
, recptr
);
1351 * Write the IMPDEF records, if any.
1353 for (imp
= imphead
; imp
; imp
= imp
->next
) {
1355 recptr
= obj_write_rword (recptr
, 0xA0); /* comment class A0 */
1356 recptr
= obj_write_byte (recptr
, 1); /* subfunction 1: IMPDEF */
1358 recptr
= obj_write_byte (recptr
, 0); /* import by name */
1360 recptr
= obj_write_byte (recptr
, 1); /* import by ordinal */
1361 recptr
= obj_write_name (recptr
, imp
->extname
);
1362 recptr
= obj_write_name (recptr
, imp
->libname
);
1364 recptr
= obj_write_name (recptr
, imp
->impname
);
1366 recptr
= obj_write_word (recptr
, imp
->impindex
);
1367 obj_record (COMENT
, record
, recptr
);
1371 * Write the EXPDEF records, if any.
1373 for (export
= exphead
; export
; export
= export
->next
) {
1375 recptr
= obj_write_rword (recptr
, 0xA0); /* comment class A0 */
1376 recptr
= obj_write_byte (recptr
, 2); /* subfunction 1: EXPDEF */
1377 recptr
= obj_write_byte (recptr
, export
->flags
);
1378 recptr
= obj_write_name (recptr
, export
->extname
);
1379 recptr
= obj_write_name (recptr
, export
->intname
);
1380 if (export
->flags
& EXPDEF_FLAG_ORDINAL
)
1381 recptr
= obj_write_word (recptr
, export
->ordinal
);
1382 obj_record (COMENT
, record
, recptr
);
1386 * Write the first LNAMES record, containing LNAME one, which
1387 * is null. Also initialise the LNAME counter.
1390 recptr
= obj_write_name (recptr
, "");
1391 obj_record (LNAMES
, record
, recptr
);
1395 * Write the SEGDEF records. Each has an associated LNAMES
1398 for (seg
= seghead
; seg
; seg
= seg
->next
) {
1399 int new_segdef
; /* do we use the newer record type? */
1401 int sn
, cn
, on
; /* seg, class, overlay LNAME idx */
1403 if (seg
->use32
|| seg
->currentpos
>= 0x10000L
)
1409 recptr
= obj_write_name (recptr
, seg
->name
);
1411 if (seg
->segclass
) {
1412 recptr
= obj_write_name (recptr
, seg
->segclass
);
1417 recptr
= obj_write_name (recptr
, seg
->overlay
);
1421 obj_record (LNAMES
, record
, recptr
);
1423 acbp
= (seg
->combine
<< 2); /* C field */
1425 if (seg
->currentpos
>= 0x10000L
&& !new_segdef
)
1426 acbp
|= 0x02; /* B bit */
1429 acbp
|= 0x01; /* P bit is Use32 flag */
1432 if (seg
->align
>= SEG_ABS
)
1434 else if (seg
->align
>= 4096) {
1435 if (seg
->align
> 4096)
1436 error(ERR_NONFATAL
, "segment `%s' requires more alignment"
1437 " than OBJ format supports", seg
->name
);
1438 acbp
|= 0xC0; /* PharLap extension */
1439 } else if (seg
->align
>= 256) {
1441 } else if (seg
->align
>= 16) {
1443 } else if (seg
->align
>= 4) {
1445 } else if (seg
->align
>= 2) {
1451 recptr
= obj_write_byte (recptr
, acbp
);
1452 if (seg
->align
& SEG_ABS
) {
1453 recptr
= obj_write_word (recptr
, seg
->align
- SEG_ABS
);
1454 recptr
= obj_write_byte (recptr
, 0);
1457 recptr
= obj_write_dword (recptr
, seg
->currentpos
);
1459 recptr
= obj_write_word (recptr
, seg
->currentpos
& 0xFFFF);
1460 recptr
= obj_write_index (recptr
, sn
);
1461 recptr
= obj_write_index (recptr
, cn
);
1462 recptr
= obj_write_index (recptr
, on
);
1464 obj_record (SEGDEF
+1, record
, recptr
);
1466 obj_record (SEGDEF
, record
, recptr
);
1470 * Write some LNAMES for the group names. lname_idx is left
1471 * alone here - it will catch up when we write the GRPDEFs.
1474 for (grp
= grphead
; grp
; grp
= grp
->next
) {
1475 if (recptr
- record
+ strlen(grp
->name
)+2 > 1024) {
1476 obj_record (LNAMES
, record
, recptr
);
1479 recptr
= obj_write_name (recptr
, grp
->name
);
1481 if (recptr
> record
)
1482 obj_record (LNAMES
, record
, recptr
);
1485 * Write the GRPDEF records.
1487 for (grp
= grphead
; grp
; grp
= grp
->next
) {
1490 if (grp
->nindices
!= grp
->nentries
) {
1491 for (i
= grp
->nindices
; i
< grp
->nentries
; i
++) {
1492 error(ERR_NONFATAL
, "group `%s' contains undefined segment"
1493 " `%s'", grp
->name
, grp
->segs
[i
].name
);
1494 nasm_free (grp
->segs
[i
].name
);
1495 grp
->segs
[i
].name
= NULL
;
1499 recptr
= obj_write_index (recptr
, lname_idx
++);
1500 for (i
= 0; i
< grp
->nindices
; i
++) {
1501 recptr
= obj_write_byte (recptr
, 0xFF);
1502 recptr
= obj_write_index (recptr
, grp
->segs
[i
].index
);
1504 obj_record (GRPDEF
, record
, recptr
);
1508 * Write the PUBDEF records: first the ones in the segments,
1509 * then the far-absolutes.
1511 for (seg
= seghead
; seg
; seg
= seg
->next
) {
1515 recptr
= obj_write_index (recptr
, seg
->grp
? seg
->grp
->obj_index
: 0);
1516 recptr
= obj_write_index (recptr
, seg
->obj_index
);
1522 for (pub
= seg
->pubhead
; pub
; pub
= pub
->next
) {
1523 if (recptr
- record
+ strlen(pub
->name
) + 7 > 1024) {
1525 obj_record (rectype
, record
, recptr
);
1527 recptr
= obj_write_index (recptr
, 0);
1528 recptr
= obj_write_index (recptr
, seg
->obj_index
);
1530 recptr
= obj_write_name (recptr
, pub
->name
);
1532 recptr
= obj_write_dword (recptr
, pub
->offset
);
1534 recptr
= obj_write_word (recptr
, pub
->offset
);
1535 recptr
= obj_write_index (recptr
, 0);
1539 obj_record (rectype
, record
, recptr
);
1541 for (pub
= fpubhead
; pub
; pub
= pub
->next
) { /* pub-crawl :-) */
1543 recptr
= obj_write_index (recptr
, 0); /* no group */
1544 recptr
= obj_write_index (recptr
, 0); /* no segment either */
1545 recptr
= obj_write_word (recptr
, pub
->segment
);
1546 recptr
= obj_write_name (recptr
, pub
->name
);
1547 recptr
= obj_write_word (recptr
, pub
->offset
);
1548 recptr
= obj_write_index (recptr
, 0);
1549 obj_record (PUBDEF
, record
, recptr
);
1553 * Write the EXTDEF and COMDEF records, in order.
1556 for (ext
= exthead
; ext
; ext
= ext
->next
) {
1557 if (ext
->commonsize
== 0) {
1558 /* dj@delorie.com: check for buffer overrun before we overrun it */
1559 if (recptr
- record
+ strlen(ext
->name
)+2 > RECORD_MAX
) {
1560 obj_record (EXTDEF
, record
, recptr
);
1563 recptr
= obj_write_name (recptr
, ext
->name
);
1564 recptr
= obj_write_index (recptr
, 0);
1566 if (recptr
> record
)
1567 obj_record (EXTDEF
, record
, recptr
);
1569 if (ext
->commonsize
) {
1570 recptr
= obj_write_name (recptr
, ext
->name
);
1571 recptr
= obj_write_index (recptr
, 0);
1572 if (ext
->commonelem
) {
1573 recptr
= obj_write_byte (recptr
, 0x61);/* far communal */
1574 recptr
= obj_write_value (recptr
, (ext
->commonsize
/
1576 recptr
= obj_write_value (recptr
, ext
->commonelem
);
1578 recptr
= obj_write_byte (recptr
, 0x62);/* near communal */
1579 recptr
= obj_write_value (recptr
, ext
->commonsize
);
1581 obj_record (COMDEF
, record
, recptr
);
1586 if (recptr
> record
)
1587 obj_record (EXTDEF
, record
, recptr
);
1590 * Write a COMENT record stating that the linker's first pass
1591 * may stop processing at this point. Exception is if our
1592 * MODEND record specifies a start point, in which case,
1593 * according to some variants of the documentation, this COMENT
1594 * should be omitted. So we'll omit it just in case.
1596 if (obj_entry_seg
== NO_SEG
) {
1598 recptr
= obj_write_rword (recptr
, 0x40A2);
1599 recptr
= obj_write_byte (recptr
, 1);
1600 obj_record (COMENT
, record
, recptr
);
1604 * Write the LEDATA/FIXUPP pairs.
1606 for (data
= datahead
; data
; data
= data
->next
) {
1607 if (data
->nonempty
) {
1608 obj_record (data
->letype
, data
->ledata
, data
->lptr
);
1609 if (data
->fptr
!= data
->fixupp
)
1610 obj_record (data
->ftype
, data
->fixupp
, data
->fptr
);
1615 * Write the MODEND module end marker.
1619 if (obj_entry_seg
!= NO_SEG
) {
1620 recptr
= obj_write_byte (recptr
, 0xC1);
1622 * Find the segment in the segment list.
1624 for (seg
= seghead
; seg
; seg
= seg
->next
) {
1625 if (seg
->index
== obj_entry_seg
) {
1627 recptr
= obj_write_byte (recptr
, 0x10);
1628 recptr
= obj_write_index (recptr
, seg
->grp
->obj_index
);
1630 recptr
= obj_write_byte (recptr
, 0x50);
1632 recptr
= obj_write_index (recptr
, seg
->obj_index
);
1635 recptr
= obj_write_dword (recptr
, obj_entry_ofs
);
1637 recptr
= obj_write_word (recptr
, obj_entry_ofs
);
1642 error(ERR_NONFATAL
, "entry point is not in this module");
1644 recptr
= obj_write_byte (recptr
, 0);
1645 obj_record (rectype
, record
, recptr
);
1648 static unsigned char *obj_write_data(unsigned char *ptr
,
1649 unsigned char *data
, int len
) {
1655 static unsigned char *obj_write_byte(unsigned char *ptr
, int data
) {
1660 static unsigned char *obj_write_word(unsigned char *ptr
, int data
) {
1661 *ptr
++ = data
& 0xFF;
1662 *ptr
++ = (data
>> 8) & 0xFF;
1666 static unsigned char *obj_write_dword(unsigned char *ptr
, long data
) {
1667 *ptr
++ = data
& 0xFF;
1668 *ptr
++ = (data
>> 8) & 0xFF;
1669 *ptr
++ = (data
>> 16) & 0xFF;
1670 *ptr
++ = (data
>> 24) & 0xFF;
1674 static unsigned char *obj_write_rword(unsigned char *ptr
, int data
) {
1675 *ptr
++ = (data
>> 8) & 0xFF;
1676 *ptr
++ = data
& 0xFF;
1680 static unsigned char *obj_write_name(unsigned char *ptr
, char *data
) {
1681 *ptr
++ = strlen(data
);
1682 if (obj_uppercase
) {
1684 *ptr
++ = (unsigned char) toupper(*data
);
1689 *ptr
++ = (unsigned char) *data
++;
1694 static unsigned char *obj_write_index(unsigned char *ptr
, int data
) {
1698 *ptr
++ = 0x80 | ((data
>> 8) & 0x7F);
1699 *ptr
++ = data
& 0xFF;
1704 static unsigned char *obj_write_value(unsigned char *ptr
,
1705 unsigned long data
) {
1708 else if (data
<= 0xFFFF) {
1710 *ptr
++ = data
& 0xFF;
1711 *ptr
++ = (data
>> 8) & 0xFF;
1712 } else if (data
<= 0xFFFFFFL
) {
1714 *ptr
++ = data
& 0xFF;
1715 *ptr
++ = (data
>> 8) & 0xFF;
1716 *ptr
++ = (data
>> 16) & 0xFF;
1719 *ptr
++ = data
& 0xFF;
1720 *ptr
++ = (data
>> 8) & 0xFF;
1721 *ptr
++ = (data
>> 16) & 0xFF;
1722 *ptr
++ = (data
>> 24) & 0xFF;
1727 static void obj_record(int type
, unsigned char *start
, unsigned char *end
) {
1728 unsigned long cksum
, len
;
1733 cksum
+= (len
& 0xFF) + ((len
>>8) & 0xFF);
1734 fwriteshort (len
, ofp
);
1735 fwrite (start
, 1, end
-start
, ofp
);
1738 fputc ( (-(long)cksum
) & 0xFF, ofp
);
1741 static char *obj_stdmac
[] = {
1742 "%define __SECT__ [section .text]",
1743 "%imacro group 1+.nolist",
1746 "%imacro uppercase 1+.nolist",
1749 "%imacro export 1+.nolist",
1752 "%imacro import 1+.nolist",
1758 struct ofmt of_obj
= {
1759 "Microsoft MS-DOS 16-bit OMF object files",