1 /* outobj.c output routines for the Netwide Assembler to produce
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.
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
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
);
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
)
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,
168 static ObjRecord
*obj_emit(ObjRecord
*orp
)
172 nasm_free(orp
->back
);
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
)
192 return (obj_emit(orp
));
196 * Allocate and clear a new ObjRecord; Also sets .ori to ori_null
198 static ObjRecord
*obj_new(void)
202 orp
= obj_clear( nasm_malloc(sizeof(ObjRecord
)) );
208 * Advance to the next record because the existing one is full or its x_size
210 * Any uncommited data is moved into the next record.
212 static ObjRecord
*obj_bump(ObjRecord
*orp
)
215 int used
= orp
->used
;
216 int committed
= orp
->committed
;
219 *orp
->up
= nxt
= obj_new();
221 nxt
->type
= orp
->type
;
224 memcpy( nxt
->parm
, orp
->parm
, sizeof(orp
->parm
));
232 nxt
->committed
= nxt
->used
;
233 memcpy( nxt
->buf
+ nxt
->committed
, orp
->buf
+ committed
, used
);
234 nxt
->used
= nxt
->committed
+ used
;
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
)
248 if (!orp
->committed
) {
251 orp
->committed
= orp
->used
;
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
;
270 static ObjRecord
*obj_byte(ObjRecord
*orp
, unsigned char val
)
272 orp
= obj_check(orp
, 1);
273 orp
->buf
[orp
->used
] = val
;
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;
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
;
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;
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
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))
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
)
343 orp
= obj_force(orp
, 32);
344 if (orp
->x_size
== 32)
345 return (obj_dword(orp
, val
));
347 return (obj_word(orp
, val
));
353 static ObjRecord
*obj_index(ObjRecord
*orp
, unsigned int val
)
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
)
366 return ( obj_byte(orp
, val
) );
368 orp
= obj_byte(orp
, 129);
369 return ( obj_word(orp
, val
) );
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
);
385 orp
= obj_check(orp
, len
+1);
386 ptr
= orp
->buf
+ orp
->used
;
391 *ptr
++ = toupper(*name
);
394 memcpy(ptr
, name
, len
);
399 * Initializer for an LEDATA record.
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
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
];
462 static evalfunc evaluate
;
463 static ldfunc deflabel
;
465 static long first_seg
;
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 */
478 struct LineNumber
*next
;
479 struct Segment
*segment
;
484 static struct FileName
{
485 struct FileName
*next
;
487 struct LineNumber
*lnhead
, **lntail
;
491 static struct Array
{
495 } *arrhead
, **arrtail
;
497 #define ARRAYBOT 31 /* magic number for first array index */
500 static struct Public
{
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
;
512 long commonelem
; /* element size if FAR, else zero */
513 int index
; /* OBJ-file external index */
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 */
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
];
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 */
548 long use32
; /* is this segment 32-bit? */
549 struct Public
*pubhead
, **pubtail
, *lochead
, **loctail
;
551 char *segclass
, *overlay
; /* `class' is a C++ keyword :-) */
553 } *seghead
, **segtail
, *obj_seg_needs_update
;
555 static struct Group
{
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... */
565 } segs
[GROUP_MAX
]; /* ...in this */
566 } *grphead
, **grptail
, *obj_grp_needs_update
;
568 static struct ImpDef
{
572 unsigned int impindex
;
574 } *imphead
, **imptail
;
576 static struct ExpDef
{
580 unsigned int ordinal
;
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
;
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
)
603 first_seg
= seg_alloc();
606 fpubtail
= &fpubhead
;
617 seghead
= obj_seg_needs_update
= NULL
;
619 grphead
= obj_grp_needs_update
= NULL
;
621 obj_entry_seg
= NO_SEG
;
622 obj_uppercase
= FALSE
;
625 of_obj
.current_dfmt
->init (&of_obj
,NULL
,fp
,errfunc
);
628 static int obj_set_info(enum geninfo type
, char **val
)
635 static void obj_cleanup (int debuginfo
)
637 obj_write_file(debuginfo
);
638 of_obj
.current_dfmt
->cleanup();
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
);
649 nasm_free (segtmp
->segclass
);
650 nasm_free (segtmp
->overlay
);
654 struct Public
*pubtmp
= fpubhead
;
655 fpubhead
= fpubhead
->next
;
656 nasm_free (pubtmp
->name
);
660 struct External
*exttmp
= exthead
;
661 exthead
= exthead
->next
;
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 */
673 struct ExpDef
*exptmp
= exphead
;
674 exphead
= exphead
->next
;
675 nasm_free (exptmp
->extname
);
676 nasm_free (exptmp
->intname
);
680 struct ExtBack
*ebtmp
= ebhead
;
681 ebhead
= ebhead
->next
;
685 struct Group
*grptmp
= grphead
;
686 grphead
= grphead
->next
;
691 static void obj_ext_set_defwrt (struct External
*ext
, char *id
)
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
;
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
;
712 ext
->defwrt_type
= DEFWRT_STRING
;
713 ext
->defwrt_ptr
.string
= id
;
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
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
;
741 int used_special
= FALSE
; /* have we used the special text? */
744 * If it's a special-retry from pass two, discard it.
750 * First check for the double-period, signifying something
753 if (name
[0] == '.' && name
[1] == '.' && name
[2] != '@') {
754 if (!strcmp(name
, "..start")) {
755 obj_entry_seg
= segment
;
756 obj_entry_ofs
= offset
;
759 error (ERR_NONFATAL
, "unrecognised special symbol `%s'", name
);
765 if (obj_seg_needs_update
) {
766 obj_seg_needs_update
->name
= name
;
768 } else if (obj_grp_needs_update
) {
769 obj_grp_needs_update
->name
= name
;
772 if (segment
< SEG_ABS
&& segment
!= NO_SEG
&& segment
% 2)
775 if (segment
>= SEG_ABS
|| segment
== NO_SEG
) {
777 * SEG_ABS subcase of (ii).
782 pub
= *fpubtail
= nasm_malloc(sizeof(*pub
));
783 fpubtail
= &pub
->next
;
785 pub
->name
= nasm_strdup(name
);
786 pub
->offset
= offset
;
787 pub
->segment
= (segment
== NO_SEG
? 0 : segment
& ~SEG_ABS
);
790 error(ERR_NONFATAL
, "OBJ supports no special symbol features"
791 " for this symbol type");
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
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?
813 seg
->pubtail
= &loc
->next
;
815 loc
->name
= nasm_strdup(name
);
816 loc
->offset
= offset
;
819 error(ERR_NONFATAL
, "OBJ supports no special symbol features"
820 " for this symbol type");
828 ext
= *exttail
= nasm_malloc(sizeof(*ext
));
830 exttail
= &ext
->next
;
832 ext
->defwrt_type
= DEFWRT_NONE
;
833 if (is_global
== 2) {
834 ext
->commonsize
= offset
;
835 ext
->commonelem
= 1; /* default FAR */
843 * Now process the special text, if any, to find default-WRT
844 * specifications and common-variable element-size and near/far
847 while (special
&& *special
) {
851 * We might have a default-WRT specification.
853 if (!nasm_strnicmp(special
, "wrt", 3)) {
857 special
+= strspn(special
, " \t");
858 p
= nasm_strndup(special
, len
= strcspn(special
, ":"));
859 obj_ext_set_defwrt (ext
, p
);
861 if (*special
&& *special
!= ':')
862 error(ERR_NONFATAL
, "`:' expected in special symbol"
863 " text for `%s'", ext
->name
);
864 else if (*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)) {
876 error(ERR_NONFATAL
, "`%s': `far' keyword may only be applied"
877 " to common variables\n", ext
->name
);
879 special
+= strspn(special
, " \t");
880 } else if (!nasm_strnicmp(special
, "near", 4)) {
884 error(ERR_NONFATAL
, "`%s': `far' keyword may only be applied"
885 " to common variables\n", ext
->name
);
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
899 if (ext
->commonsize
) {
901 struct tokenval tokval
;
904 stdscan_bufptr
= special
;
905 tokval
.t_type
= TOKEN_INVALID
;
906 e
= evaluate(stdscan
, NULL
, &tokval
, NULL
, 1, error
, NULL
);
909 error (ERR_NONFATAL
, "cannot use relocatable"
910 " expression as common-variable element size");
912 ext
->commonelem
= reloc_value(e
);
914 special
= stdscan_bufptr
;
916 error (ERR_NONFATAL
, "`%s': element-size specifications only"
917 " apply to common variables", ext
->name
);
918 while (*special
&& *special
!= ':')
929 eb
= *ebtail
= nasm_malloc(sizeof(*eb
));
933 while (i
> EXT_BLKSIZ
) {
937 eb
= *ebtail
= nasm_malloc(sizeof(*eb
));
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
)
959 unsigned char *ucdata
;
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]"
975 * If `any_segs' is still FALSE, we must define a default
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
)
991 error (ERR_PANIC
, "code directed to nonexistent segment?");
994 orp
->parm
[0] = seg
->currentpos
;
996 size
= type
& OUT_SIZMASK
;
997 realtype
= type
& OUT_TYPMASK
;
998 if (realtype
== OUT_RAWDATA
) {
1002 orp
= obj_check(seg
->orp
, 1);
1003 len
= RECORD_MAX
- orp
->used
;
1006 memcpy (orp
->buf
+orp
->used
, ucdata
, len
);
1007 orp
->committed
= orp
->used
+= len
;
1008 orp
->parm
[0] = seg
->currentpos
+= len
;
1013 else if (realtype
== OUT_ADDRESS
|| realtype
== OUT_REL2ADR
||
1014 realtype
== OUT_REL4ADR
)
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"
1024 ldata
= *(long *)data
;
1025 if (realtype
== OUT_REL2ADR
) {
1029 if (realtype
== OUT_REL4ADR
) {
1034 orp
= obj_word (orp
, ldata
);
1036 orp
= obj_dword (orp
, ldata
);
1038 if (segment
< SEG_ABS
&& (segment
!= NO_SEG
&& segment
% 2) &&
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.
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),
1056 seg
->currentpos
+= size
;
1057 } else if (realtype
== OUT_RESERVE
) {
1059 orp
= obj_bump(orp
);
1060 seg
->currentpos
+= size
;
1065 static void obj_write_fixup (ObjRecord
*orp
, int bytes
,
1066 int segrel
, long seg
, long wrt
, struct Segment
*segto
)
1071 struct Segment
*s
= NULL
;
1072 struct Group
*g
= NULL
;
1073 struct External
*e
= NULL
;
1077 error(ERR_NONFATAL
, "`obj' output driver does not support"
1078 " one-byte relocations");
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 */
1089 forp
->type
= FIXU32
;
1091 forp
->type
= FIXUPP
;
1096 locat
= FIX_16_SELECTOR
;
1099 error(ERR_PANIC
, "OBJ: 4-byte segment base fixup got"
1100 " through sanity check");
1104 locat
= (bytes
== 2) ? FIX_16_OFFSET
: FIX_32_OFFSET
;
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
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
)
1126 method
= 4, tidx
= s
->obj_index
;
1128 for (g
= grphead
; g
; g
= g
->next
)
1129 if (g
->index
== seg
)
1132 method
= 5, tidx
= g
->obj_index
;
1135 struct ExtBack
*eb
= ebhead
;
1136 while (i
> EXT_BLKSIZ
) {
1144 method
= 6, e
= eb
->exts
[i
], tidx
= e
->index
;
1147 "unrecognised segment value in obj_write_fixup");
1152 * If no WRT given, assume the natural default, which is method
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
;
1170 error(ERR_NONFATAL
, "default WRT specification for"
1171 " external `%s' unresolved", e
->name
);
1172 method
|= 0x50, fidx
= -1; /* got to do _something_ */
1175 method
|= 0x50, fidx
= -1;
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)
1185 method
|= 0x00, fidx
= s
->obj_index
;
1187 for (g
= grphead
; g
; g
= g
->next
)
1188 if (g
->index
== wrt
-1)
1191 method
|= 0x10, fidx
= g
->obj_index
;
1194 struct ExtBack
*eb
= ebhead
;
1195 while (i
> EXT_BLKSIZ
) {
1203 method
|= 0x20, fidx
= eb
->exts
[i
]->index
;
1206 "unrecognised WRT value in obj_write_fixup");
1211 forp
= obj_byte (forp
, method
);
1213 forp
= obj_index (forp
, fidx
);
1214 forp
= obj_index (forp
, tidx
);
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.
1231 struct Segment
*seg
;
1233 struct External
**extp
;
1234 int obj_idx
, i
, attrs
, rn_error
;
1238 * Look for segment attributes.
1241 while (*name
== '.')
1242 name
++; /* hack, but a documented one */
1244 while (*p
&& !isspace(*p
))
1248 while (*p
&& isspace(*p
))
1252 while (*p
&& !isspace(*p
))
1256 while (*p
&& isspace(*p
))
1264 for (seg
= seghead
; seg
; seg
= seg
->next
) {
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");
1278 *segtail
= seg
= nasm_malloc(sizeof(*seg
));
1280 segtail
= &seg
->next
;
1281 seg
->index
= (any_segs
? seg_alloc() : first_seg
);
1282 seg
->obj_index
= obj_idx
;
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.
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"))
1322 else if (!nasm_stricmp(p
, "use32"))
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
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.
1337 for (grp
= grphead
; grp
; grp
= grp
->next
)
1338 if (!strcmp(grp
->name
, "FLAT"))
1341 obj_directive ("group", "FLAT", 1);
1342 for (grp
= grphead
; grp
; grp
= grp
->next
)
1343 if (!strcmp(grp
->name
, "FLAT"))
1346 error (ERR_PANIC
, "failure to define FLAT?!");
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
);
1357 error (ERR_NONFATAL
, "segment alignment should be"
1360 switch ((int) seg
->align
) {
1365 case 256: /* PAGE */
1366 case 4096: /* PharLap extension */
1369 error(ERR_WARNING
, "OBJ format does not support alignment"
1370 " of 8: rounding up to 16");
1376 error(ERR_WARNING
, "OBJ format does not support alignment"
1377 " of %d: rounding up to 256", seg
->align
);
1383 error(ERR_WARNING
, "OBJ format does not support alignment"
1384 " of %d: rounding up to 4096", seg
->align
);
1388 error(ERR_NONFATAL
, "invalid alignment value %d",
1393 } else if (!nasm_strnicmp(p
, "absolute=", 9)) {
1394 seg
->align
= SEG_ABS
+ readnum(p
+9, &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
);
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
;
1420 error(ERR_WARNING
, "segment `%s' is already part of"
1421 " a group: first one takes precedence",
1430 * Walk through the list of externals with unresolved
1431 * default-WRT clauses, and resolve any that point at this
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
;
1443 extp
= &(*extp
)->next_dws
;
1454 static int obj_directive (char *directive
, char *value
, int pass
)
1456 if (!strcmp(directive
, "group")) {
1460 struct Segment
*seg
;
1461 struct External
**extp
;
1466 q
++; /* hack, but a documented one */
1468 while (*q
&& !isspace(*q
))
1472 while (*q
&& isspace(*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.
1482 * error(ERR_NONFATAL,"GROUP directive contains no segments");
1488 for (grp
= grphead
; grp
; grp
= grp
->next
) {
1490 if (!strcmp(grp
->name
, v
)) {
1491 error(ERR_NONFATAL
, "group `%s' defined twice", v
);
1496 *grptail
= grp
= nasm_malloc(sizeof(*grp
));
1498 grptail
= &grp
->next
;
1499 grp
->index
= seg_alloc();
1500 grp
->obj_index
= obj_idx
;
1501 grp
->nindices
= grp
->nentries
= 0;
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
;
1511 while (*q
&& !isspace(*q
))
1515 while (*q
&& isspace(*q
))
1519 * Now p contains a segment name. Find it.
1521 for (seg
= seghead
; seg
; seg
= seg
->next
)
1522 if (!strcmp(seg
->name
, p
))
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
;
1532 error(ERR_WARNING
, "segment `%s' is already part of"
1533 " a group: first one takes precedence",
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
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
;
1560 extp
= &(*extp
)->next_dws
;
1565 if (!strcmp(directive
, "uppercase")) {
1566 obj_uppercase
= TRUE
;
1569 if (!strcmp(directive
, "import")) {
1570 char *q
, *extname
, *libname
, *impname
;
1573 return 1; /* ignore in pass two */
1574 extname
= q
= value
;
1575 while (*q
&& !isspace(*q
))
1579 while (*q
&& isspace(*q
))
1584 while (*q
&& !isspace(*q
))
1588 while (*q
&& isspace(*q
))
1594 if (!*extname
|| !*libname
)
1595 error(ERR_NONFATAL
, "`import' directive requires symbol name"
1596 " and library name");
1601 imp
= *imptail
= nasm_malloc(sizeof(struct ImpDef
));
1602 imptail
= &imp
->next
;
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
);
1610 imp
->impname
= NULL
;
1615 if (!strcmp(directive
, "export")) {
1616 char *q
, *extname
, *intname
, *v
;
1617 struct ExpDef
*export
;
1619 unsigned int ordinal
= 0;
1622 return 1; /* ignore in pass two */
1623 intname
= q
= value
;
1624 while (*q
&& !isspace(*q
))
1628 while (*q
&& isspace(*q
))
1633 while (*q
&& !isspace(*q
))
1637 while (*q
&& isspace(*q
))
1642 error(ERR_NONFATAL
, "`export' directive requires export name");
1651 while (*q
&& !isspace(*q
))
1655 while (*q
&& isspace(*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)) {
1664 flags
|= EXPDEF_MASK_PARMCNT
& readnum(v
+5, &err
);
1667 "value `%s' for `parm' is non-numeric", v
+5);
1672 ordinal
= readnum(v
, &err
);
1674 error(ERR_NONFATAL
, "unrecognised export qualifier `%s'",
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
;
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)
1708 * Might be an external with a default WRT.
1711 struct ExtBack
*eb
= ebhead
;
1714 while (i
> EXT_BLKSIZ
) {
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;
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 */
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
;
1756 struct Public
*pub
, *loc
;
1757 struct External
*ext
;
1759 struct ExpDef
*export
;
1760 static char boast
[] = "The Netwide Assembler " NASM_VER
;
1765 * Write the THEADR module header.
1769 obj_name (orp
, obj_infile
);
1773 * Write the NASM boast comment.
1776 obj_rword (orp
, 0); /* comment type zero */
1777 obj_name (orp
, boast
);
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 */
1788 obj_byte (orp
, 0); /* import by name */
1790 obj_byte (orp
, 1); /* import by ordinal */
1791 obj_name (orp
, imp
->extname
);
1792 obj_name (orp
, imp
->libname
);
1794 obj_name (orp
, imp
->impname
);
1796 obj_word (orp
, imp
->impindex
);
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
);
1814 /* we're using extended OMF if we put in debug info*/
1817 obj_byte (orp
, 0x40);
1818 obj_byte (orp
, dEXTENDED
);
1823 * Write the first LNAMES record, containing LNAME one, which
1824 * is null. Also initialise the LNAME counter.
1830 * Write some LNAMES for the segment names
1832 for (seg
= seghead
; seg
; seg
= seg
->next
) {
1833 orp
= obj_name (orp
, seg
->name
);
1835 orp
= obj_name (orp
, seg
->segclass
);
1837 orp
= obj_name (orp
, seg
->overlay
);
1841 * Write some LNAMES for the group names
1843 for (grp
= grphead
; grp
; grp
= grp
->next
) {
1844 orp
= obj_name (orp
, grp
->name
);
1851 * Write the SEGDEF records.
1854 for (seg
= seghead
; seg
; seg
= seg
->next
) {
1856 unsigned long seglen
= seg
->currentpos
;
1858 acbp
= (seg
->combine
<< 2); /* C field */
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 */
1869 if (seg
->align
>= SEG_ABS
)
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) {
1878 } else if (seg
->align
>= 16) {
1880 } else if (seg
->align
>= 4) {
1882 } else if (seg
->align
>= 2) {
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);
1900 * Write the GRPDEF records.
1903 for (grp
= grphead
; grp
; grp
= grp
->next
) {
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
);
1923 * Write the PUBDEF records: first the ones in the segments,
1924 * then the far-absolutes.
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 */
1941 for (pub
= fpubhead
; pub
; pub
= pub
->next
) { /* pub-crawl :-) */
1942 if (orp
->parm
[2] != pub
->segment
) {
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 */
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
) {
1963 orp
= obj_name (orp
, ext
->name
);
1964 orp
= obj_index (orp
, 0);
1966 if (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
);
1977 orp
= obj_byte (orp
, 0x62);/* near communal */
1978 orp
= obj_value (orp
, ext
->commonsize
);
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
) {
1996 obj_byte (orp
, 0x40);
1997 obj_byte (orp
, dLINKPASS
);
2003 * 1) put out the compiler type
2004 * 2) Put out the type info. The only type we are using is near label #19
2008 struct Array
*arrtmp
= arrhead
;
2010 obj_byte (orp
, 0x40);
2011 obj_byte (orp
, dCOMPDEF
);
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
2098 orp
->ori
= ori_null
;
2099 obj_byte (orp
, 0x40);
2100 obj_byte (orp
, dFILNAME
);
2102 obj_name( orp
,fn
->name
);
2106 /* write out line numbers this file */
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
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
);
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
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
;
2142 error(ERR_NONFATAL
, "entry point is not in this module");
2146 * get ready to put out symbol records
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
);
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
);
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.
2195 orp
->ori
= ori_null
;
2196 if (entry_seg_ptr
) {
2197 obj_byte (orp
, 0xC1);
2198 seg
= entry_seg_ptr
;
2200 obj_byte (orp
, 0x10);
2201 obj_index (orp
, seg
->grp
->obj_index
);
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
);
2220 void obj_fwrite(ObjRecord
*orp
)
2222 unsigned int cksum
, len
;
2226 if (orp
->x_size
== 32)
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
++)
2235 fputc ( (-cksum
) & 0xFF, ofp
);
2238 static char *obj_stdmac
[] = {
2239 "%define __SECT__ [section .text]",
2240 "%imacro group 1+.nolist",
2243 "%imacro uppercase 0+.nolist",
2246 "%imacro export 1+.nolist",
2249 "%imacro import 1+.nolist",
2252 "%macro __NASM_CDecl__ 1",
2257 void dbgbi_init(struct ofmt
* of
, void * id
, FILE * fp
, efunc error
)
2266 arrindex
= ARRAYBOT
;
2270 static void dbgbi_cleanup(void)
2272 struct Segment
*segtmp
;
2274 struct FileName
*fntemp
= fnhead
;
2275 while (fnhead
->lnhead
) {
2276 struct LineNumber
*lntemp
= fnhead
->lnhead
;
2277 fnhead
->lnhead
= lntemp
->next
;
2280 fnhead
= fnhead
->next
;
2281 nasm_free (fntemp
->name
);
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
);
2293 struct Array
*arrtmp
= arrhead
;
2294 arrhead
= arrhead
->next
;
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
)
2309 * If `any_segs' is still FALSE, we must define a default
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
)
2325 error (ERR_PANIC
, "lineno directed to nonexistent segment?");
2327 for (fn
= fnhead
; fn
; fn
= fnhead
->next
)
2328 if (!nasm_stricmp(lnfname
,fn
->name
))
2331 fn
= nasm_malloc ( sizeof( *fn
));
2332 fn
->name
= nasm_malloc ( strlen(lnfname
) + 1) ;
2333 strcpy (fn
->name
,lnfname
);
2335 fn
->lntail
= & fn
->lnhead
;
2340 ln
= nasm_malloc ( sizeof( *ln
));
2342 ln
->offset
= seg
->currentpos
;
2343 ln
->lineno
= lineno
;
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
;
2357 * If it's a special-retry from pass two, discard it.
2363 * First check for the double-period, signifying something
2366 if (name
[0] == '.' && name
[1] == '.' && name
[2] != '@') {
2373 if (obj_seg_needs_update
) {
2375 } else if (obj_grp_needs_update
) {
2378 if (segment
< SEG_ABS
&& segment
!= NO_SEG
&& segment
% 2)
2381 if (segment
>= SEG_ABS
|| segment
== NO_SEG
) {
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
;
2401 loc
->name
= nasm_strdup(name
);
2402 loc
->offset
= offset
;
2405 static void dbgbi_typevalue (long type
)
2408 int elem
= TYM_ELEMENTS(type
);
2409 type
= TYM_TYPE(type
);
2416 last_defined
->type
= 8; /* unsigned char */
2420 last_defined
->type
= 10; /* unsigned word */
2424 last_defined
->type
= 12; /* unsigned dword */
2428 last_defined
->type
= 14; /* float */
2432 last_defined
->type
= 15; /* qword */
2436 last_defined
->type
= 16; /* TBYTE */
2440 last_defined
->type
= 0x19; /*label */
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
++;
2453 arrtail
= & (arrtmp
->next
);
2455 last_defined
= NULL
;
2457 static void dbgbi_output (int output_type
, void *param
)
2462 static struct dfmt borland_debug_form
= {
2463 "Borland Debug Records",
2474 static struct dfmt
*borland_debug_arr
[3] = {
2475 &borland_debug_form
,
2480 struct ofmt of_obj
= {
2481 "MS-DOS 16-bit/32-bit OMF object files",