1 /* outbin.c output routines for the Netwide Assembler to produce
2 * flat-form binary 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.
10 /* This is the extended version of NASM's original binary output
11 * format. It is backward compatible with the original BIN format,
12 * and contains support for multiple sections and advanced section
17 * - Users can create an arbitrary number of sections; they are not
18 * limited to just ".text", ".data", and ".bss".
20 * - Sections can be either progbits or nobits type.
22 * - You can specify that they be aligned at a certian boundary
23 * following the previous section ("align="), or positioned at an
24 * arbitrary byte-granular location ("start=").
26 * - You can specify a "virtual" start address for a section, which
27 * will be used for the calculation for all address references
28 * with respect to that section ("vstart=").
30 * - The ORG directive, as well as the section/segment directive
31 * arguments ("align=", "start=", "vstart="), can take a critical
32 * expression as their value. For example: "align=(1 << 12)".
34 * - You can generate map files using the 'map' directive.
38 /* Uncomment the following define if you want sections to adapt
39 * their progbits/nobits state depending on what type of
40 * instructions are issued, rather than defaulting to progbits.
41 * Note that this behavior violates the specification.
43 #define ABIN_SMART_ADAPT
60 struct ofmt
*bin_get_ofmt(); /* Prototype goes here since no header file. */
62 static FILE *fp
, *rf
= NULL
;
65 /* Section flags keep track of which attributes the user has defined. */
66 #define START_DEFINED 0x001
67 #define ALIGN_DEFINED 0x002
68 #define FOLLOWS_DEFINED 0x004
69 #define VSTART_DEFINED 0x008
70 #define VALIGN_DEFINED 0x010
71 #define VFOLLOWS_DEFINED 0x020
72 #define TYPE_DEFINED 0x040
73 #define TYPE_PROGBITS 0x080
74 #define TYPE_NOBITS 0x100
76 /* This struct is used to keep track of symbols for map-file generation. */
77 static struct bin_label
79 struct bin_label
*next
;
80 } *no_seg_labels
, **nsl_tail
;
84 struct SAA
* contents
;
85 long length
; /* section length in bytes */
87 /* Section attributes */
88 int flags
; /* see flag definitions above */
89 unsigned long align
; /* section alignment */
90 unsigned long valign
; /* notional section alignment */
91 unsigned long start
; /* section start address */
92 unsigned long vstart
; /* section virtual start address */
93 char *follows
; /* the section that this one will follow */
94 char *vfollows
; /* the section that this one will notionally follow */
95 long start_index
; /* NASM section id for non-relocated version */
96 long vstart_index
; /* the NASM section id */
98 struct bin_label
*labels
; /* linked-list of label handles for map output. */
99 struct bin_label
**labels_end
; /* Holds address of end of labels list. */
100 struct Section
*ifollows
; /* Points to previous section (implicit follows). */
101 struct Section
*next
; /* This links sections with a defined start address. */
103 /* The extended bin format allows for sections to have a "virtual"
104 * start address. This is accomplished by creating two sections:
105 * one beginning at the Load Memory Address and the other beginning
106 * at the Virtual Memory Address. The LMA section is only used to
107 * define the section.<section_name>.start label, but there isn't
108 * any other good way for us to handle that label.
111 } *sections
, *last_section
;
113 static struct Reloc
{
119 struct Section
*target
;
120 } *relocs
, **reloctail
;
122 extern char *stdscan_bufptr
;
123 extern int lookup_label (char *label
, long *segment
, long *offset
);
125 static unsigned char format_mode
; /* 0 = original bin, 1 = extended bin */
126 static long current_section
; /* only really needed if format_mode = 0 */
127 static unsigned long origin
;
128 static int origin_defined
;
130 /* Stuff we need for map-file generation. */
132 #define MAP_SUMMARY 2
133 #define MAP_SECTIONS 4
134 #define MAP_SYMBOLS 8
135 static int map_control
= 0;
136 static char *infile
, *outfile
;
138 static const char *bin_stdmac
[] = {
139 "%define __SECT__ [section .text]",
140 "%imacro org 1+.nolist",
143 "%macro __NASM_CDecl__ 1",
148 static void add_reloc(struct Section
*s
, long bytes
, long secref
, long secrel
)
151 r
= *reloctail
= nasm_malloc(sizeof(struct Reloc
));
152 reloctail
= &r
->next
;
161 static struct Section
*find_section_by_name(const char *name
)
164 for (s
= sections
; s
; s
= s
->next
)
165 if (!strcmp(s
->name
,name
)) break;
169 static struct Section
*find_section_by_index(long index
)
172 for (s
= sections
; s
; s
= s
->next
)
173 if ((index
== s
->vstart_index
) || (index
== s
->start_index
))
178 static struct Section
* create_section(char *name
)
179 { /* Create a new section. */
180 last_section
->next
= nasm_malloc(sizeof(struct Section
));
181 last_section
->next
->ifollows
= last_section
;
182 last_section
= last_section
->next
;
183 last_section
->labels
= NULL
;
184 last_section
->labels_end
= &(last_section
->labels
);
186 /* Initialize section attributes. */
187 last_section
->name
= nasm_strdup(name
);
188 last_section
->contents
= saa_init(1L);
189 last_section
->follows
= last_section
->vfollows
= 0;
190 last_section
->length
= 0;
191 last_section
->flags
= 0;
192 last_section
->next
= NULL
;
194 /* Register our sections with NASM. */
195 last_section
->vstart_index
= seg_alloc();
196 last_section
->start_index
= seg_alloc();
200 static void bin_cleanup (int debuginfo
)
201 { struct Section
*g
, **gp
;
202 struct Section
*gs
= NULL
, **gsp
;
203 struct Section
*s
, **sp
;
204 struct Section
*nobits
= NULL
, **nt
;
205 struct Section
* last_progbits
;
212 fprintf(stdout
, "bin_cleanup: Sections were initially referenced in this order:\n");
213 for (h
= 0, s
= sections
; s
; h
++, s
= s
->next
)
214 fprintf(stdout
, "%i. %s\n", h
, s
->name
);
217 /* Assembly has completed, so now we need to generate the output file.
218 * Step 1: Separate progbits and nobits sections into separate lists.
219 * Step 2: Sort the progbits sections into their output order.
220 * Step 3: Compute start addresses for all progbits sections.
221 * Step 4: Compute vstart addresses for all sections.
222 * Step 5: Apply relocations.
223 * Step 6: Write the sections' data to the output file.
224 * Step 7: Generate the map file.
225 * Step 8: Release all allocated memory.
228 /* To do: Smart section-type adaptation could leave some empty sections
229 * without a defined type (progbits/nobits). Won't fix now since this
230 * feature will be disabled. */
233 /* Step 1: Split progbits and nobits sections into separate lists. */
236 /* Move nobits sections into a separate list. Also pre-process nobits
237 * sections' attributes. */
238 for (sp
= §ions
->next
, s
= sections
->next
; s
; s
= *sp
)
239 { /* Skip progbits sections. */
240 if (s
->flags
& TYPE_PROGBITS
)
241 { sp
= &s
->next
; continue;
243 /* Do some special pre-processing on nobits sections' attributes. */
244 if (s
->flags
& (START_DEFINED
| ALIGN_DEFINED
| FOLLOWS_DEFINED
))
245 { /* Check for a mixture of real and virtual section attributes. */
246 if (s
->flags
& (VSTART_DEFINED
| VALIGN_DEFINED
| VFOLLOWS_DEFINED
))
247 error(ERR_FATAL
, "cannot mix real and virtual attributes"
248 " in nobits section (%s)", s
->name
);
249 /* Real and virtual attributes mean the same thing for nobits sections. */
250 if (s
->flags
& START_DEFINED
)
251 { s
->vstart
= s
->start
; s
->flags
|= VSTART_DEFINED
;
253 if (s
->flags
& ALIGN_DEFINED
)
254 { s
->valign
= s
->align
; s
->flags
|= VALIGN_DEFINED
;
256 if (s
->flags
& FOLLOWS_DEFINED
)
257 { s
->vfollows
= s
->follows
; s
->flags
|= VFOLLOWS_DEFINED
;
258 s
->flags
&= ~FOLLOWS_DEFINED
;
261 /* Every section must have a start address. */
262 if (s
->flags
& VSTART_DEFINED
)
263 { s
->start
= s
->vstart
; s
->flags
|= START_DEFINED
;
265 /* Move the section into the nobits list. */
266 *sp
= s
->next
; s
->next
= NULL
;
267 *nt
= s
; nt
= &s
->next
;
270 /* Step 2: Sort the progbits sections into their output order. */
272 /* In Step 2 we move around sections in groups. A group
273 * begins with a section (group leader) that has a user-
274 * defined start address or follows section. The remainder
275 * of the group is made up of the sections that implicitly
276 * follow the group leader (i.e., they were defined after
277 * the group leader and were not given an explicit start
278 * address or follows section by the user). */
280 /* For anyone attempting to read this code:
281 * g (group) points to a group of sections, the first one of which has
282 * a user-defined start address or follows section.
283 * gp (g previous) holds the location of the pointer to g.
284 * gs (g scan) is a temp variable that we use to scan to the end of the group.
285 * gsp (gs previous) holds the location of the pointer to gs.
286 * nt (nobits tail) points to the nobits section-list tail.
289 /* Link all 'follows' groups to their proper position. To do
290 * this we need to know three things: the start of the group
291 * to relocate (g), the section it is following (s), and the
292 * end of the group we're relocating (gs). */
293 for (gp
= §ions
, g
= sections
; g
; g
= gs
)
294 { /* Find the next follows group that is out of place (g). */
295 if (!(g
->flags
& FOLLOWS_DEFINED
))
297 { if ((g
->next
->flags
& FOLLOWS_DEFINED
) &&
298 strcmp(g
->name
, g
->next
->follows
)) break;
302 gp
= &g
->next
; g
= g
->next
;
304 /* Find the section that this group follows (s). */
305 for (sp
= §ions
, s
= sections
;
306 s
&& strcmp(s
->name
, g
->follows
);
307 sp
= &s
->next
, s
= s
->next
);
308 if (!s
) error(ERR_FATAL
, "section %s follows an invalid or"
309 " unknown section (%s)", g
->name
, g
->follows
);
310 if (s
->next
&& (s
->next
->flags
& FOLLOWS_DEFINED
) &&
311 !strcmp(s
->name
, s
->next
->follows
))
312 error(ERR_FATAL
, "sections %s and %s can't both follow"
313 " section %s", g
->name
, s
->next
->name
, s
->name
);
314 /* Find the end of the current follows group (gs). */
315 for (gsp
= &g
->next
, gs
= g
->next
;
316 gs
&& (gs
!= s
) && !(gs
->flags
& START_DEFINED
);
317 gsp
= &gs
->next
, gs
= gs
->next
)
318 { if (gs
->next
&& (gs
->next
->flags
& FOLLOWS_DEFINED
) &&
319 strcmp(gs
->name
, gs
->next
->follows
))
320 { gsp
= &gs
->next
; gs
= gs
->next
; break;
323 /* Re-link the group after its follows section. */
324 *gsp
= s
->next
; s
->next
= g
;
328 /* Link all 'start' groups to their proper position. Once
329 * again we need to know g, s, and gs (see above). The main
330 * difference is we already know g since we sort by moving
331 * groups from the 'unsorted' list into a 'sorted' list (g
332 * will always be the first section in the unsorted list). */
333 for (g
= sections
, sections
= NULL
; g
; g
= gs
)
334 { /* Find the section that we will insert this group before (s). */
335 for (sp
= §ions
, s
= sections
; s
; sp
= &s
->next
, s
= s
->next
)
336 if ((s
->flags
& START_DEFINED
) && (g
->start
< s
->start
)) break;
337 /* Find the end of the group (gs). */
338 for (gs
= g
->next
, gsp
= &g
->next
;
339 gs
&& !(gs
->flags
& START_DEFINED
);
340 gsp
= &gs
->next
, gs
= gs
->next
);
341 /* Re-link the group before the target section. */
346 /* Step 3: Compute start addresses for all progbits sections. */
348 /* Make sure we have an origin and a start address for the first section. */
350 switch (sections
->flags
& (START_DEFINED
| ALIGN_DEFINED
))
351 { case START_DEFINED
| ALIGN_DEFINED
:
353 /* Make sure this section doesn't begin before the origin. */
354 if (sections
->start
< origin
) error(ERR_FATAL
, "section %s begins"
355 " before program origin", sections
->name
);
358 sections
->start
= ((origin
+ sections
->align
- 1) &
359 ~(sections
->align
- 1)); break;
361 sections
->start
= origin
;
364 { if (!(sections
->flags
& START_DEFINED
))
366 origin
= sections
->start
;
368 sections
->flags
|= START_DEFINED
;
370 /* Make sure each section has an explicit start address. If it
371 * doesn't, then compute one based its alignment and the end of
372 * the previous section. */
373 for (pend
= sections
->start
, g
= s
= sections
; g
; g
= g
->next
)
374 { /* Find the next section that could cause an overlap situation
375 * (has a defined start address, and is not zero length). */
378 s
&& ((s
->length
== 0) || !(s
->flags
& START_DEFINED
));
380 /* Compute the start address of this section, if necessary. */
381 if (!(g
->flags
& START_DEFINED
))
382 { /* Default to an alignment of 4 if unspecified. */
383 if (!(g
->flags
& ALIGN_DEFINED
))
384 { g
->align
= 4; g
->flags
|= ALIGN_DEFINED
;
386 /* Set the section start address. */
387 g
->start
= (pend
+ g
->align
- 1) & ~(g
->align
- 1);
388 g
->flags
|= START_DEFINED
;
390 /* Ugly special case for progbits sections' virtual attributes:
391 * If there is a defined valign, but no vstart and no vfollows, then
392 * we valign after the previous progbits section. This case doesn't
393 * really make much sense for progbits sections with a defined start
394 * address, but it is possible and we must do *something*.
395 * Not-so-ugly special case:
396 * If a progbits section has no virtual attributes, we set the
397 * vstart equal to the start address. */
398 if (!(g
->flags
& (VSTART_DEFINED
| VFOLLOWS_DEFINED
)))
399 { if (g
->flags
& VALIGN_DEFINED
)
400 g
->vstart
= (pend
+ g
->valign
- 1) & ~(g
->valign
- 1);
401 else g
->vstart
= g
->start
;
402 g
->flags
|= VSTART_DEFINED
;
404 /* Ignore zero-length sections. */
405 if (g
->start
< pend
) continue;
406 /* Compute the span of this section. */
407 pend
= g
->start
+ g
->length
;
408 /* Check for section overlap. */
410 { if (g
->start
> s
->start
)
411 error(ERR_FATAL
, "sections %s ~ %s and %s overlap!",
412 gs
->name
, g
->name
, s
->name
);
414 error(ERR_FATAL
, "sections %s and %s overlap!",
417 /* Remember this section as the latest >0 length section. */
421 /* Step 4: Compute vstart addresses for all sections. */
423 /* Attach the nobits sections to the end of the progbits sections. */
424 for (s
= sections
; s
->next
; s
= s
->next
); s
->next
= nobits
;
426 /* Scan for sections that don't have a vstart address. If we find one we'll
427 * attempt to compute its vstart. If we can't compute the vstart, we leave
428 * it alone and come back to it in a subsequent scan. We continue scanning
429 * and re-scanning until we've gone one full cycle without computing any
432 { /* Do one full scan of the sections list. */
433 for (h
= 0, g
= sections
; g
; g
= g
->next
)
434 { if (g
->flags
& VSTART_DEFINED
) continue;
435 /* Find the section that this one virtually follows. */
436 if (g
->flags
& VFOLLOWS_DEFINED
)
437 { for (s
= sections
; s
&& strcmp(g
->vfollows
, s
->name
); s
= s
->next
);
438 if (!s
) error(ERR_FATAL
, "section %s vfollows unknown section (%s)",
439 g
->name
, g
->vfollows
);
441 else if (g
->ifollows
!= NULL
)
442 for (s
= sections
; s
&& (s
!= g
->ifollows
); s
= s
->next
);
443 /* The .bss section is the only one with ifollows = NULL. In this case we
444 * implicitly follow the last progbits section. */
445 else s
= last_progbits
;
447 /* If the section we're following has a vstart, we can proceed. */
448 if (s
->flags
& VSTART_DEFINED
)
449 { /* Default to virtual alignment of four. */
450 if (!(g
->flags
& VALIGN_DEFINED
))
451 { g
->valign
= 4; g
->flags
|= VALIGN_DEFINED
;
453 /* Compute the vstart address. */
454 g
->vstart
= (s
->vstart
+ s
->length
+ g
->valign
- 1) & ~(g
->valign
- 1);
455 g
->flags
|= VSTART_DEFINED
; h
++;
456 /* Start and vstart mean the same thing for nobits sections. */
457 if (g
->flags
& TYPE_NOBITS
) g
->start
= g
->vstart
;
462 /* Now check for any circular vfollows references, which will manifest
463 * themselves as sections without a defined vstart. */
464 for (h
= 0, s
= sections
; s
; s
= s
->next
)
465 { if (!(s
->flags
& VSTART_DEFINED
))
466 { /* Non-fatal errors after assembly has completed are generally a
467 * no-no, but we'll throw a fatal one eventually so it's ok. */
468 error(ERR_NONFATAL
, "cannot compute vstart for section %s", s
->name
);
472 if (h
) error(ERR_FATAL
, "circular vfollows path detected");
475 fprintf(stdout
, "bin_cleanup: Confirm final section order for output file:\n");
476 for (h
= 0, s
= sections
; s
&& (s
->flags
& TYPE_PROGBITS
); h
++, s
= s
->next
)
477 fprintf(stdout
, "%i. %s\n", h
, s
->name
);
481 /* Step 5: Apply relocations. */
483 /* Prepare the sections for relocating. */
484 for (s
= sections
; s
; s
= s
->next
) saa_rewind(s
->contents
);
485 /* Apply relocations. */
486 for (r
= relocs
; r
; r
= r
->next
)
487 { unsigned char *p
, *q
, mydata
[4];
490 saa_fread (r
->target
->contents
, r
->posn
, mydata
, r
->bytes
);
495 { l
+= ((long)*p
++) << 8;
497 { l
+= ((long)*p
++) << 16;
498 l
+= ((long)*p
++) << 24;
502 s
= find_section_by_index(r
->secref
);
504 { if (r
->secref
== s
->start_index
) l
+= s
->start
;
507 s
= find_section_by_index(r
->secrel
);
509 { if (r
->secrel
== s
->start_index
) l
-= s
->start
;
513 if (r
->bytes
== 4) WRITELONG(q
, l
);
514 else if (r
->bytes
== 2) WRITESHORT(q
, l
);
515 else *q
++ = (unsigned char) (l
& 0xFF);
516 saa_fwrite(r
->target
->contents
, r
->posn
, mydata
, r
->bytes
);
520 /* Step 6: Write the section data to the output file. */
522 /* Write the progbits sections to the output file. */
523 for(pend
= origin
, s
= sections
; s
&& (s
->flags
& TYPE_PROGBITS
); s
= s
->next
)
524 { /* Skip zero-length sections. */
525 if (s
->length
== 0) continue;
526 /* Pad the space between sections. */
527 for (h
= s
->start
- pend
; h
; h
--)
529 /* Write the section to the output file. */
530 if (s
->length
> 0) saa_fpwrite(s
->contents
, fp
);
531 pend
= s
->start
+ s
->length
;
533 /* Done writing the file, so close it. */
537 /* Step 7: Generate the map file. */
540 { const char *not_defined
= { "not defined" };
542 /* Display input and output file names. */
543 fprintf(rf
, "\n- NASM Map file ");
544 for (h
= 63; h
; h
--) fputc('-', rf
);
545 fprintf(rf
, "\n\nSource file: %s\nOutput file: %s\n\n",
548 if (map_control
& MAP_ORIGIN
)
549 { /* Display program origin. */
550 fprintf(rf
, "-- Program origin ");
551 for (h
= 61; h
; h
--) fputc('-', rf
);
552 fprintf(rf
, "\n\n%08lX\n\n", origin
);
554 /* Display sections summary. */
555 if (map_control
& MAP_SUMMARY
)
556 { fprintf(rf
, "-- Sections (summary) ");
557 for (h
= 57; h
; h
--) fputc('-', rf
);
558 fprintf(rf
, "\n\nVstart Start Stop "
559 "Length Class Name\n");
560 for (s
= sections
; s
; s
= s
->next
)
561 { fprintf(rf
, "%08lX %08lX %08lX %08lX ",
562 s
->vstart
, s
->start
, s
->start
+ s
->length
, s
->length
);
563 if (s
->flags
& TYPE_PROGBITS
) fprintf(rf
, "progbits ");
564 else fprintf(rf
, "nobits ");
565 fprintf(rf
, "%s\n", s
->name
);
569 /* Display detailed section information. */
570 if (map_control
& MAP_SECTIONS
)
571 { fprintf(rf
, "-- Sections (detailed) ");
572 for (h
= 56; h
; h
--) fputc('-', rf
);
574 for (s
= sections
; s
; s
= s
->next
)
575 { fprintf(rf
, "---- Section %s ", s
->name
);
576 for (h
= 65 - strlen(s
->name
); h
; h
--) fputc('-', rf
);
577 fprintf(rf
, "\n\nclass: ");
578 if (s
->flags
& TYPE_PROGBITS
) fprintf(rf
, "progbits");
579 else fprintf(rf
, "nobits");
580 fprintf(rf
, "\nlength: %08lX\nstart: %08lX"
581 "\nalign: ", s
->length
, s
->start
);
582 if (s
->flags
& ALIGN_DEFINED
) fprintf(rf
, "%08lX", s
->align
);
583 else fprintf(rf
, not_defined
);
584 fprintf(rf
, "\nfollows: ");
585 if (s
->flags
& FOLLOWS_DEFINED
) fprintf(rf
, "%s", s
->follows
);
586 else fprintf(rf
, not_defined
);
587 fprintf(rf
, "\nvstart: %08lX\nvalign: ", s
->vstart
);
588 if (s
->flags
& VALIGN_DEFINED
) fprintf(rf
, "%08lX", s
->valign
);
589 else fprintf(rf
, not_defined
);
590 fprintf(rf
, "\nvfollows: ");
591 if (s
->flags
& VFOLLOWS_DEFINED
) fprintf(rf
, "%s", s
->vfollows
);
592 else fprintf(rf
, not_defined
);
596 /* Display symbols information. */
597 if (map_control
& MAP_SYMBOLS
)
598 { long segment
, offset
;
600 fprintf(rf
, "-- Symbols ");
601 for (h
= 68; h
; h
--) fputc('-', rf
);
604 { fprintf(rf
, "---- No Section ");
605 for (h
= 63; h
; h
--) fputc('-', rf
);
606 fprintf(rf
, "\n\nValue Name\n");
607 for (l
= no_seg_labels
; l
; l
= l
->next
)
608 { lookup_label(l
->name
, &segment
, &offset
);
609 fprintf(rf
, "%08lX %s\n", offset
, l
->name
);
613 for (s
= sections
; s
; s
= s
->next
)
615 { fprintf(rf
, "---- Section %s ", s
->name
);
616 for (h
= 65 - strlen(s
->name
); h
; h
--) fputc('-', rf
);
617 fprintf(rf
, "\n\nReal Virtual Name\n");
618 for (l
= s
->labels
; l
; l
= l
->next
)
619 { lookup_label(l
->name
, &segment
, &offset
);
620 fprintf(rf
, "%08lX %08lX %s\n", s
->start
+ offset
,
621 s
->vstart
+ offset
, l
->name
);
629 /* Close the report file. */
630 if (map_control
&& (rf
!= stdout
) && (rf
!= stderr
))
634 /* Step 8: Release all allocated memory. */
636 /* Free sections, label pointer structs, etc.. */
638 { s
= sections
; sections
= s
->next
;
639 saa_free(s
->contents
);
641 if (s
->flags
& FOLLOWS_DEFINED
) nasm_free(s
->follows
);
642 if (s
->flags
& VFOLLOWS_DEFINED
) nasm_free(s
->vfollows
);
644 { l
= s
->labels
; s
->labels
= l
->next
;
650 /* Free no-section labels. */
651 while (no_seg_labels
)
652 { l
= no_seg_labels
; no_seg_labels
= l
->next
;
656 /* Free relocation structures. */
664 static void bin_out (long segto
, const void *data
, unsigned long type
,
665 long segment
, long wrt
)
666 { unsigned char *p
, mydata
[4];
671 { wrt
= NO_SEG
; /* continue to do _something_ */
673 "WRT not supported by binary output format");
676 /* Handle absolute-assembly (structure definitions). */
678 { if ((type
& OUT_TYPMASK
) != OUT_RESERVE
)
679 error (ERR_NONFATAL
, "attempt to assemble code in"
680 " [ABSOLUTE] space");
684 /* Find the segment we are targeting. */
685 s
= find_section_by_index(segto
);
687 error (ERR_PANIC
, "code directed to nonexistent segment?");
689 /* "Smart" section-type adaptation code. */
690 if (!(s
->flags
& TYPE_DEFINED
))
691 { if ((type
& OUT_TYPMASK
) == OUT_RESERVE
)
692 s
->flags
|= TYPE_DEFINED
| TYPE_NOBITS
;
693 else s
->flags
|= TYPE_DEFINED
| TYPE_PROGBITS
;
696 if ((s
->flags
& TYPE_NOBITS
) && ((type
& OUT_TYPMASK
) != OUT_RESERVE
))
697 error(ERR_WARNING
, "attempt to initialise memory in a"
698 " nobits section: ignored");
700 if ((type
& OUT_TYPMASK
) == OUT_ADDRESS
)
701 { if (segment
!= NO_SEG
&& !find_section_by_index(segment
))
703 error(ERR_NONFATAL
, "binary output format does not support"
704 " segment base references");
706 error(ERR_NONFATAL
, "binary output format does not support"
707 " external references");
710 if (s
->flags
& TYPE_PROGBITS
)
711 { if (segment
!= NO_SEG
)
712 add_reloc(s
, type
& OUT_SIZMASK
, segment
, -1L);
714 if ((type
& OUT_SIZMASK
) == 4)
715 WRITELONG(p
, *(long *)data
);
717 WRITESHORT(p
, *(long *)data
);
718 saa_wbytes(s
->contents
, mydata
, type
& OUT_SIZMASK
);
720 s
->length
+= type
& OUT_SIZMASK
;
722 else if ((type
& OUT_TYPMASK
) == OUT_RAWDATA
)
723 { type
&= OUT_SIZMASK
;
724 if (s
->flags
& TYPE_PROGBITS
) saa_wbytes(s
->contents
, data
, type
);
727 else if ((type
& OUT_TYPMASK
) == OUT_RESERVE
)
728 { type
&= OUT_SIZMASK
;
729 if (s
->flags
& TYPE_PROGBITS
)
730 { error(ERR_WARNING
, "uninitialised space declared in"
731 " %s section: zeroing", s
->name
);
732 saa_wbytes (s
->contents
, NULL
, type
);
736 else if ((type
& OUT_TYPMASK
) == OUT_REL2ADR
||
737 (type
& OUT_TYPMASK
) == OUT_REL4ADR
)
738 { realbytes
= ((type
& OUT_TYPMASK
) == OUT_REL4ADR
? 4 : 2);
739 if (segment
!= NO_SEG
&& !find_section_by_index(segment
))
741 error(ERR_NONFATAL
, "binary output format does not support"
742 " segment base references");
744 error(ERR_NONFATAL
, "binary output format does not support"
745 " external references");
748 if (s
->flags
& TYPE_PROGBITS
)
749 { add_reloc(s
, realbytes
, segment
, segto
);
752 WRITELONG(p
, *(long*)data
- realbytes
- s
->length
);
754 WRITESHORT(p
, *(long*)data
- realbytes
- s
->length
);
755 saa_wbytes(s
->contents
, mydata
, realbytes
);
757 s
->length
+= realbytes
;
761 static void bin_deflabel (char *name
, long segment
, long offset
,
762 int is_global
, char *special
)
763 { (void) segment
; /* Don't warn that this parameter is unused */
764 (void) offset
; /* Don't warn that this parameter is unused */
767 error (ERR_NONFATAL
, "binary format does not support any"
768 " special symbol types");
769 else if (name
[0] == '.' && name
[1] == '.' && name
[2] != '@')
770 error (ERR_NONFATAL
, "unrecognised special symbol `%s'", name
);
771 else if (is_global
== 2)
772 error (ERR_NONFATAL
, "binary output format does not support common"
776 struct bin_label
***ltp
;
778 /* Remember label definition so we can look it up later when
779 * creating the map file. */
780 s
= find_section_by_index(segment
);
781 if (s
) ltp
= &(s
->labels_end
);
782 else ltp
= &nsl_tail
;
783 (**ltp
) = nasm_malloc(sizeof(struct bin_label
));
784 (**ltp
)->name
= name
;
785 (**ltp
)->next
= NULL
;
786 *ltp
= &((**ltp
)->next
);
791 /* These constants and the following function are used
792 * by bin_secname() to parse attribute assignments. */
794 enum { ATTRIB_START
, ATTRIB_ALIGN
, ATTRIB_FOLLOWS
,
795 ATTRIB_VSTART
, ATTRIB_VALIGN
, ATTRIB_VFOLLOWS
,
796 ATTRIB_NOBITS
, ATTRIB_PROGBITS
};
798 static int bin_read_attribute(char **line
, int *attribute
, unsigned long *value
)
800 int attrib_name_size
;
801 struct tokenval tokval
;
804 /* Skip whitespace. */
805 while (**line
&& isspace(**line
)) (*line
)++;
806 if (!**line
) return 0;
808 /* Figure out what attribute we're reading. */
809 if (!nasm_strnicmp(*line
,"align=", 6))
810 { *attribute
= ATTRIB_ALIGN
;
811 attrib_name_size
= 6;
813 else if (format_mode
)
814 { if (!nasm_strnicmp(*line
,"start=", 6))
815 { *attribute
= ATTRIB_START
;
816 attrib_name_size
= 6;
818 else if (!nasm_strnicmp(*line
,"follows=", 8))
819 { *attribute
= ATTRIB_FOLLOWS
;
820 *line
+= 8; return 1;
822 else if (!nasm_strnicmp(*line
,"vstart=", 7))
823 { *attribute
= ATTRIB_VSTART
;
824 attrib_name_size
= 7;
826 else if (!nasm_strnicmp(*line
,"valign=", 7))
827 { *attribute
= ATTRIB_VALIGN
;
828 attrib_name_size
= 7;
830 else if (!nasm_strnicmp(*line
,"vfollows=", 9))
831 { *attribute
= ATTRIB_VFOLLOWS
;
832 *line
+= 9; return 1;
834 else if (!nasm_strnicmp(*line
,"nobits", 6) &&
835 (isspace((*line
)[6]) || ((*line
)[6] == '\0')))
836 { *attribute
= ATTRIB_NOBITS
;
837 *line
+= 6; return 1;
839 else if (!nasm_strnicmp(*line
,"progbits", 8) &&
840 (isspace((*line
)[8]) || ((*line
)[8] == '\0')))
841 { *attribute
= ATTRIB_PROGBITS
;
842 *line
+= 8; return 1;
848 /* Find the end of the expression. */
849 if ((*line
)[attrib_name_size
] != '(')
851 /* Single term (no parenthesis). */
852 exp
= *line
+= attrib_name_size
;
853 while (**line
&& !isspace(**line
)) (*line
)++;
855 { **line
= '\0'; (*line
)++;
862 /* Full expression (delimited by parenthesis) */
863 exp
= *line
+= attrib_name_size
+ 1;
865 { (*line
) += strcspn(*line
, "()'\"");
867 { ++(*line
); ++pcount
;
870 { ++(*line
); --pcount
;
873 if ((**line
== '"') || (**line
== '\''))
877 if (**line
== c
) break;
880 { error(ERR_NONFATAL
, "invalid syntax in `section' directive");
886 { error(ERR_NONFATAL
, "expecting `)'");
890 *(*line
- 1) = '\0'; /* Terminate the expression. */
893 /* Check for no value given. */
895 { error(ERR_WARNING
, "No value given to attribute in"
896 " `section' directive");
900 /* Read and evaluate the expression. */
902 stdscan_bufptr
= exp
;
903 tokval
.t_type
= TOKEN_INVALID
;
904 e
= evaluate(stdscan
, NULL
, &tokval
, NULL
, 1, error
, NULL
);
906 { if (!is_really_simple(e
))
907 { error(ERR_NONFATAL
, "section attribute value must be"
908 " a critical expression");
913 { error(ERR_NONFATAL
, "Invalid attribute value"
914 " specified in `section' directive.");
917 *value
= (unsigned long) reloc_value(e
);
921 static void bin_assign_attributes(struct Section
*sec
, char *astring
)
922 { int attribute
, check
;
927 { /* Get the next attribute. */
928 check
= bin_read_attribute(&astring
, &attribute
, &value
);
929 /* Skip bad attribute. */
930 if (check
== -1) continue;
931 /* Unknown section attribute, so skip it and warn the user. */
933 { if (!*astring
) break; /* End of line. */
935 { p
= astring
; while (*astring
&& !isspace(*astring
)) astring
++;
937 { *astring
= '\0'; astring
++;
939 error(ERR_WARNING
, "ignoring unknown section attribute:"
946 { /* Handle nobits attribute. */
948 if ((sec
->flags
& TYPE_DEFINED
) && (sec
->flags
& TYPE_PROGBITS
))
949 error(ERR_NONFATAL
, "attempt to change section type"
950 " from progbits to nobits");
951 else sec
->flags
|= TYPE_DEFINED
| TYPE_NOBITS
;
954 /* Handle progbits attribute. */
955 case ATTRIB_PROGBITS
:
956 if ((sec
->flags
& TYPE_DEFINED
) && (sec
->flags
& TYPE_NOBITS
))
957 error(ERR_NONFATAL
, "attempt to change section type"
958 " from nobits to progbits");
959 else sec
->flags
|= TYPE_DEFINED
| TYPE_PROGBITS
;
962 /* Handle align attribute. */
964 if (!format_mode
&& (!strcmp(sec
->name
, ".text")))
965 error(ERR_NONFATAL
, "cannot specify an alignment"
966 " to the .text section");
968 { if (!value
|| ((value
- 1) & value
))
969 error(ERR_NONFATAL
, "argument to `align' is not a"
972 { /* Alignment is already satisfied if the previous
973 * align value is greater. */
974 if ((sec
->flags
& ALIGN_DEFINED
) && (value
< sec
->align
))
977 /* Don't allow a conflicting align value. */
978 if ((sec
->flags
& START_DEFINED
) && (sec
->start
& (value
- 1)))
979 error(ERR_NONFATAL
, "`align' value conflicts "
980 "with section start address");
982 { sec
->align
= value
; sec
->flags
|= ALIGN_DEFINED
;
988 /* Handle valign attribute. */
990 if (!value
|| ((value
- 1) & value
))
991 error(ERR_NONFATAL
, "argument to `valign' is not a"
994 { /* Alignment is already satisfied if the previous
995 * align value is greater. */
996 if ((sec
->flags
& VALIGN_DEFINED
) && (value
< sec
->valign
))
999 /* Don't allow a conflicting valign value. */
1000 if ((sec
->flags
& VSTART_DEFINED
) && (sec
->vstart
& (value
- 1)))
1001 error(ERR_NONFATAL
, "`valign' value conflicts "
1002 "with `vstart' address");
1004 { sec
->valign
= value
; sec
->flags
|= VALIGN_DEFINED
;
1009 /* Handle start attribute. */
1011 if (sec
->flags
& FOLLOWS_DEFINED
)
1012 error(ERR_NONFATAL
, "cannot combine `start' and `follows'"
1013 " section attributes");
1015 error(ERR_NONFATAL
, "attempt to specify a negative"
1016 " section start address");
1017 else if ((sec
->flags
& START_DEFINED
) && (value
!= sec
->start
))
1018 error(ERR_NONFATAL
, "section start address redefined");
1020 { sec
->start
= value
; sec
->flags
|= START_DEFINED
;
1021 if (sec
->flags
& ALIGN_DEFINED
)
1022 { if (sec
->start
& (sec
->align
- 1))
1023 error (ERR_NONFATAL
, "`start' address conflicts"
1024 " with section alignment");
1025 sec
->flags
^= ALIGN_DEFINED
;
1030 /* Handle vstart attribute. */
1032 if (sec
->flags
& VFOLLOWS_DEFINED
)
1033 error(ERR_NONFATAL
, "cannot combine `vstart' and `vfollows'"
1034 " section attributes");
1035 else if ((sec
->flags
& VSTART_DEFINED
) && (value
!= sec
->vstart
))
1036 error(ERR_NONFATAL
, "section virtual start address"
1037 " (vstart) redefined");
1039 { sec
->vstart
= value
; sec
->flags
|= VSTART_DEFINED
;
1040 if (sec
->flags
& VALIGN_DEFINED
)
1041 { if (sec
->vstart
& (sec
->valign
- 1))
1042 error (ERR_NONFATAL
, "`vstart' address conflicts"
1043 " with `valign' value");
1044 sec
->flags
^= VALIGN_DEFINED
;
1049 /* Handle follows attribute. */
1050 case ATTRIB_FOLLOWS
:
1051 p
= astring
; astring
+= strcspn(astring
, " \t");
1053 error(ERR_NONFATAL
, "expecting section name for `follows'"
1056 { *(astring
++) = '\0';
1057 if (sec
->flags
& START_DEFINED
)
1058 error(ERR_NONFATAL
, "cannot combine `start' and `follows'"
1059 " section attributes");
1060 sec
->follows
= nasm_strdup(p
);
1061 sec
->flags
|= FOLLOWS_DEFINED
;
1065 /* Handle vfollows attribute. */
1066 case ATTRIB_VFOLLOWS
:
1067 if (sec
->flags
& VSTART_DEFINED
)
1068 error(ERR_NONFATAL
, "cannot combine `vstart' and `vfollows'"
1069 " section attributes");
1071 { p
= astring
; astring
+= strcspn(astring
, " \t");
1073 error(ERR_NONFATAL
, "expecting section name for `vfollows'"
1076 { *(astring
++) = '\0';
1077 sec
->vfollows
= nasm_strdup(p
);
1078 sec
->flags
|= VFOLLOWS_DEFINED
;
1086 static void bin_define_section_labels()
1087 { static int labels_defined
= 0;
1088 struct Section
* sec
;
1092 if (labels_defined
) return;
1093 for (sec
= sections
; sec
; sec
= sec
->next
)
1094 { base_len
= strlen(sec
->name
) + 8;
1095 label_name
= nasm_malloc(base_len
+ 8);
1096 strcpy(label_name
, "section.");
1097 strcpy(label_name
+ 8, sec
->name
);
1099 /* section.<name>.start */
1100 strcpy(label_name
+ base_len
, ".start");
1101 define_label(label_name
, sec
->start_index
, 0L,
1102 NULL
, 0, 0, bin_get_ofmt(), error
);
1104 /* section.<name>.vstart */
1105 strcpy(label_name
+ base_len
, ".vstart");
1106 define_label(label_name
, sec
->vstart_index
, 0L,
1107 NULL
, 0, 0, bin_get_ofmt(), error
);
1109 nasm_free(label_name
);
1114 static long bin_secname(char *name
, int pass
, int *bits
)
1116 struct Section
*sec
;
1118 /* bin_secname is called with *name = NULL at the start of each
1119 * pass. Use this opportunity to establish the default section
1120 * (default is BITS-16 ".text" segment).
1123 { /* Reset ORG and section attributes at the start of each pass. */
1125 for (sec
= sections
; sec
; sec
= sec
->next
)
1126 sec
->flags
&= ~(START_DEFINED
| VSTART_DEFINED
|
1127 ALIGN_DEFINED
| VALIGN_DEFINED
);
1129 /* Define section start and vstart labels. */
1130 if (format_mode
&& (pass
!= 1)) bin_define_section_labels();
1132 /* Establish the default (.text) section. */
1134 sec
= find_section_by_name(".text");
1135 sec
->flags
|= TYPE_DEFINED
| TYPE_PROGBITS
;
1136 current_section
= sec
->vstart_index
;
1137 return current_section
;
1140 /* Attempt to find the requested section. If it does not
1141 * exist, create it. */
1143 while (*p
&& !isspace(*p
)) p
++;
1144 if (*p
) *p
++ = '\0';
1145 sec
= find_section_by_name(name
);
1147 { sec
= create_section(name
);
1148 if (!strcmp(name
, ".data"))
1149 sec
->flags
|= TYPE_DEFINED
| TYPE_PROGBITS
;
1150 else if (!strcmp(name
, ".bss"))
1151 { sec
->flags
|= TYPE_DEFINED
| TYPE_NOBITS
;
1152 sec
->ifollows
= NULL
;
1154 else if (!format_mode
)
1155 { error(ERR_NONFATAL
, "section name must be "
1156 ".text, .data, or .bss");
1157 return current_section
;
1161 /* Handle attribute assignments. */
1162 if (pass
!= 1) bin_assign_attributes(sec
, p
);
1164 #ifndef ABIN_SMART_ADAPT
1165 /* The following line disables smart adaptation of
1166 * PROGBITS/NOBITS section types (it forces sections to
1167 * default to PROGBITS). */
1168 if ((pass
!= 1) && !(sec
->flags
& TYPE_DEFINED
))
1169 sec
->flags
|= TYPE_DEFINED
| TYPE_PROGBITS
;
1172 /* Set the current section and return. */
1173 current_section
= sec
->vstart_index
;
1174 return current_section
;
1177 static int bin_directive (char *directive
, char *args
, int pass
)
1179 /* Handle ORG directive */
1180 if (!nasm_stricmp(directive
, "org"))
1181 { struct tokenval tokval
;
1182 unsigned long value
;
1186 stdscan_bufptr
= args
;
1187 tokval
.t_type
= TOKEN_INVALID
;
1188 e
= evaluate(stdscan
, NULL
, &tokval
, NULL
, 1, error
, NULL
);
1190 { if (!is_really_simple(e
))
1191 error(ERR_NONFATAL
, "org value must be a critical"
1194 { value
= reloc_value(e
);
1195 /* Check for ORG redefinition. */
1196 if (origin_defined
&& (value
!= origin
))
1197 error(ERR_NONFATAL
, "program origin redefined");
1205 error(ERR_NONFATAL
, "No or invalid offset specified"
1206 " in ORG directive.");
1210 /* The 'map' directive allows the user to generate section
1211 * and symbol information to stdout, stderr, or to a file. */
1212 else if (format_mode
&& !nasm_stricmp(directive
, "map"))
1215 if (pass
!= 1) return 1;
1216 args
+= strspn(args
, " \t");
1218 { p
= args
; args
+= strcspn(args
, " \t");
1219 if (*args
!= '\0') *(args
++) = '\0';
1220 if (!nasm_stricmp(p
, "all"))
1221 map_control
|= MAP_ORIGIN
| MAP_SUMMARY
| MAP_SECTIONS
| MAP_SYMBOLS
;
1222 else if (!nasm_stricmp(p
, "brief"))
1223 map_control
|= MAP_ORIGIN
| MAP_SUMMARY
;
1224 else if (!nasm_stricmp(p
, "sections"))
1225 map_control
|= MAP_ORIGIN
| MAP_SUMMARY
| MAP_SECTIONS
;
1226 else if (!nasm_stricmp(p
, "segments"))
1227 map_control
|= MAP_ORIGIN
| MAP_SUMMARY
| MAP_SECTIONS
;
1228 else if (!nasm_stricmp(p
, "symbols"))
1229 map_control
|= MAP_SYMBOLS
;
1231 { if (!nasm_stricmp(p
, "stdout"))
1233 else if (!nasm_stricmp(p
, "stderr"))
1236 { /* Must be a filename. */
1237 rf
= fopen(p
, "wt");
1239 { error(ERR_WARNING
, "unable to open map file `%s'", p
);
1245 else error(ERR_WARNING
, "map file already specified");
1247 if (map_control
== 0) map_control
|= MAP_ORIGIN
| MAP_SUMMARY
;
1248 if (!rf
) rf
= stdout
;
1254 static void bin_filename (char *inname
, char *outname
, efunc error
)
1255 { standard_extension(inname
, outname
, "", error
);
1256 infile
= inname
; outfile
= outname
;
1259 static long bin_segbase (long segment
)
1263 static int bin_set_info(enum geninfo type
, char **val
)
1267 static void bin_init (FILE *afp
, efunc errfunc
, ldfunc ldef
, evalfunc eval
)
1271 (void) eval
; /* Don't warn that this parameter is unused. */
1272 (void) ldef
; /* Placate optimizers. */
1275 reloctail
= &relocs
;
1277 no_seg_labels
= NULL
;
1278 nsl_tail
= &no_seg_labels
;
1279 format_mode
= 1; /* Extended bin format
1280 * (set this to zero for old bin format). */
1282 /* Create default section (.text). */
1283 sections
= last_section
= nasm_malloc(sizeof(struct Section
));
1284 last_section
->next
= NULL
;
1285 last_section
->name
= nasm_strdup(".text");
1286 last_section
->contents
= saa_init(1L);
1287 last_section
->follows
= last_section
->vfollows
= 0;
1288 last_section
->ifollows
= NULL
;
1289 last_section
->length
= 0;
1290 last_section
->flags
= TYPE_DEFINED
| TYPE_PROGBITS
;
1291 last_section
->labels
= NULL
;
1292 last_section
->labels_end
= &(last_section
->labels
);
1293 last_section
->start_index
= seg_alloc();
1294 last_section
->vstart_index
= current_section
= seg_alloc();
1297 struct ofmt of_bin
= {
1298 "flat-form binary files (e.g. DOS .COM, .SYS)",
1315 /* This is needed for bin_define_section_labels() */
1316 struct ofmt
*bin_get_ofmt()
1320 #endif /* #ifdef OF_BIN */