Update for newer RH releases
[nasm/avx512.git] / output / outbin.c
blob80be83cf3cbbd5cc4aaea45a6dd95aef1b9827c9
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.
8 */
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
13 * ordering.
15 * Feature summary:
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
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <ctype.h>
52 #include "nasm.h"
53 #include "nasmlib.h"
54 #include "labels.h"
55 #include "eval.h"
56 #include "outform.h"
58 #ifdef OF_BIN
60 struct ofmt *bin_get_ofmt(); /* Prototype goes here since no header file. */
62 static FILE *fp, *rf = NULL;
63 static efunc error;
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
78 { char * name;
79 struct bin_label *next;
80 } *no_seg_labels, **nsl_tail;
82 static struct Section
83 { char *name;
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 {
114 struct Reloc *next;
115 long posn;
116 long bytes;
117 long secref;
118 long secrel;
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. */
131 #define MAP_ORIGIN 1
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",
141 "[org %1]",
142 "%endmacro",
143 "%macro __NASM_CDecl__ 1",
144 "%endmacro",
145 NULL
148 static void add_reloc(struct Section *s, long bytes, long secref, long secrel)
149 { struct Reloc *r;
151 r = *reloctail = nasm_malloc(sizeof(struct Reloc));
152 reloctail = &r->next;
153 r->next = NULL;
154 r->posn = s->length;
155 r->bytes = bytes;
156 r->secref = secref;
157 r->secrel = secrel;
158 r->target = s;
161 static struct Section *find_section_by_name(const char *name)
162 { struct Section *s;
164 for (s = sections; s; s = s->next)
165 if (!strcmp(s->name,name)) break;
166 return s;
169 static struct Section *find_section_by_index(long index)
170 { struct Section *s;
172 for (s = sections; s; s = s->next)
173 if ((index == s->vstart_index) || (index == s->start_index))
174 break;
175 return s;
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();
197 return last_section;
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;
206 struct bin_label *l;
207 struct Reloc *r;
208 unsigned long pend;
209 int h;
211 #ifdef DEBUG
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);
215 #endif
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. */
235 nt = &nobits;
236 /* Move nobits sections into a separate list. Also pre-process nobits
237 * sections' attributes. */
238 for (sp = &sections->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 = &sections, g = sections; g; g = gs)
294 { /* Find the next follows group that is out of place (g). */
295 if (!(g->flags & FOLLOWS_DEFINED))
296 { while (g->next)
297 { if ((g->next->flags & FOLLOWS_DEFINED) &&
298 strcmp(g->name, g->next->follows)) break;
299 g = g->next;
301 if (!g->next) break;
302 gp = &g->next; g = g->next;
304 /* Find the section that this group follows (s). */
305 for (sp = &sections, 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;
325 *gp = gs;
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 = &sections, 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. */
342 *sp = g; *gsp = s;
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. */
349 if (origin_defined)
350 switch (sections->flags & (START_DEFINED | ALIGN_DEFINED))
351 { case START_DEFINED | ALIGN_DEFINED:
352 case START_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);
356 break;
357 case ALIGN_DEFINED:
358 sections->start = ((origin + sections->align - 1) &
359 ~(sections->align - 1)); break;
360 case 0:
361 sections->start = origin;
363 else
364 { if (!(sections->flags & START_DEFINED))
365 sections->start = 0;
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). */
376 if (g == s)
377 for (s = g->next;
378 s && ((s->length == 0) || !(s->flags & START_DEFINED));
379 s = s->next);
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. */
409 if (s)
410 { if (g->start > s->start)
411 error(ERR_FATAL, "sections %s ~ %s and %s overlap!",
412 gs->name, g->name, s->name);
413 if (pend > s->start)
414 error(ERR_FATAL, "sections %s and %s overlap!",
415 g->name, s->name);
417 /* Remember this section as the latest >0 length section. */
418 gs = g;
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;
425 last_progbits = s;
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
430 * vstarts. */
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;
460 } while (h);
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);
469 h++;
472 if (h) error(ERR_FATAL, "circular vfollows path detected");
474 #ifdef DEBUG
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);
478 #endif
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];
488 long l;
490 saa_fread (r->target->contents, r->posn, mydata, r->bytes);
491 p = q = mydata;
492 l = *p++;
494 if (r->bytes > 1)
495 { l += ((long)*p++) << 8;
496 if (r->bytes == 4)
497 { l += ((long)*p++) << 16;
498 l += ((long)*p++) << 24;
502 s = find_section_by_index(r->secref);
503 if (s)
504 { if (r->secref == s->start_index) l += s->start;
505 else l += s->vstart;
507 s = find_section_by_index(r->secrel);
508 if (s)
509 { if (r->secrel == s->start_index) l -= s->start;
510 else l -= s->vstart;
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--)
528 fputc('\0', fp);
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. */
534 fclose(fp);
537 /* Step 7: Generate the map file. */
539 if (map_control)
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",
546 infile, outfile);
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);
567 fprintf(rf, "\n");
569 /* Display detailed section information. */
570 if (map_control & MAP_SECTIONS)
571 { fprintf(rf, "-- Sections (detailed) ");
572 for (h = 56; h; h--) fputc('-', rf);
573 fprintf(rf, "\n\n");
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);
593 fprintf(rf, "\n\n");
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);
602 fprintf(rf, "\n\n");
603 if (no_seg_labels)
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);
611 fprintf(rf, "\n\n");
613 for (s = sections; s; s = s->next)
614 { if (s->labels)
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);
623 fprintf(rf, "\n");
629 /* Close the report file. */
630 if (map_control && (rf != stdout) && (rf != stderr))
631 fclose(rf);
634 /* Step 8: Release all allocated memory. */
636 /* Free sections, label pointer structs, etc.. */
637 while (sections)
638 { s = sections; sections = s->next;
639 saa_free(s->contents);
640 nasm_free(s->name);
641 if (s->flags & FOLLOWS_DEFINED) nasm_free(s->follows);
642 if (s->flags & VFOLLOWS_DEFINED) nasm_free(s->vfollows);
643 while (s->labels)
644 { l = s->labels; s->labels = l->next;
645 nasm_free(l);
647 nasm_free(s);
650 /* Free no-section labels. */
651 while (no_seg_labels)
652 { l = no_seg_labels; no_seg_labels = l->next;
653 nasm_free(l);
656 /* Free relocation structures. */
657 while (relocs)
658 { r = relocs->next;
659 nasm_free(relocs);
660 relocs = r;
664 static void bin_out (long segto, const void *data, unsigned long type,
665 long segment, long wrt)
666 { unsigned char *p, mydata[4];
667 struct Section *s;
668 long realbytes;
670 if (wrt != NO_SEG)
671 { wrt = NO_SEG; /* continue to do _something_ */
672 error (ERR_NONFATAL,
673 "WRT not supported by binary output format");
676 /* Handle absolute-assembly (structure definitions). */
677 if (segto == NO_SEG)
678 { if ((type & OUT_TYPMASK) != OUT_RESERVE)
679 error (ERR_NONFATAL, "attempt to assemble code in"
680 " [ABSOLUTE] space");
681 return;
684 /* Find the segment we are targeting. */
685 s = find_section_by_index(segto);
686 if (!s)
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))
702 { if (segment % 2)
703 error(ERR_NONFATAL, "binary output format does not support"
704 " segment base references");
705 else
706 error(ERR_NONFATAL, "binary output format does not support"
707 " external references");
708 segment = NO_SEG;
710 if (s->flags & TYPE_PROGBITS)
711 { if (segment != NO_SEG)
712 add_reloc(s, type & OUT_SIZMASK, segment, -1L);
713 p = mydata;
714 if ((type & OUT_SIZMASK) == 4)
715 WRITELONG(p, *(long *)data);
716 else
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);
725 s->length += 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);
734 s->length += 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))
740 { if (segment % 2)
741 error(ERR_NONFATAL, "binary output format does not support"
742 " segment base references");
743 else
744 error(ERR_NONFATAL, "binary output format does not support"
745 " external references");
746 segment = NO_SEG;
748 if (s->flags & TYPE_PROGBITS)
749 { add_reloc(s, realbytes, segment, segto);
750 p = mydata;
751 if (realbytes == 4)
752 WRITELONG(p, *(long*)data - realbytes - s->length);
753 else
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 */
766 if (special)
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"
773 " variables");
774 else
775 { struct Section *s;
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)
799 { expr *e;
800 int attrib_name_size;
801 struct tokenval tokval;
802 char *exp;
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;
844 else return 0;
846 else return 0;
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)++;
854 if (**line)
855 { **line = '\0'; (*line)++;
858 else
859 { char c;
860 int pcount = 1;
862 /* Full expression (delimited by parenthesis) */
863 exp = *line += attrib_name_size + 1;
864 while (1)
865 { (*line) += strcspn(*line, "()'\"");
866 if (**line == '(')
867 { ++(*line); ++pcount;
869 if (**line == ')')
870 { ++(*line); --pcount;
871 if (!pcount) break;
873 if ((**line == '"') || (**line == '\''))
874 { c = **line;
875 while (**line)
876 { ++(*line);
877 if (**line == c) break;
879 if (!**line)
880 { error(ERR_NONFATAL, "invalid syntax in `section' directive");
881 return -1;
883 ++(*line);
885 if (!**line)
886 { error(ERR_NONFATAL, "expecting `)'");
887 return -1;
890 *(*line - 1) = '\0'; /* Terminate the expression. */
893 /* Check for no value given. */
894 if (!*exp)
895 { error(ERR_WARNING, "No value given to attribute in"
896 " `section' directive");
897 return -1;
900 /* Read and evaluate the expression. */
901 stdscan_reset();
902 stdscan_bufptr = exp;
903 tokval.t_type = TOKEN_INVALID;
904 e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
905 if (e)
906 { if (!is_really_simple(e))
907 { error(ERR_NONFATAL, "section attribute value must be"
908 " a critical expression");
909 return -1;
912 else
913 { error(ERR_NONFATAL, "Invalid attribute value"
914 " specified in `section' directive.");
915 return -1;
917 *value = (unsigned long) reloc_value(e);
918 return 1;
921 static void bin_assign_attributes(struct Section *sec, char *astring)
922 { int attribute, check;
923 unsigned long value;
924 char *p;
926 while (1)
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. */
932 if (!check)
933 { if (!*astring) break; /* End of line. */
934 else
935 { p = astring; while (*astring && !isspace(*astring)) astring++;
936 if (*astring)
937 { *astring = '\0'; astring++;
939 error(ERR_WARNING, "ignoring unknown section attribute:"
940 " \"%s\"", p);
942 continue;
945 switch (attribute)
946 { /* Handle nobits attribute. */
947 case ATTRIB_NOBITS:
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;
952 continue;
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;
960 continue;
962 /* Handle align attribute. */
963 case ATTRIB_ALIGN:
964 if (!format_mode && (!strcmp(sec->name, ".text")))
965 error(ERR_NONFATAL, "cannot specify an alignment"
966 " to the .text section");
967 else
968 { if (!value || ((value - 1) & value))
969 error(ERR_NONFATAL, "argument to `align' is not a"
970 " power of two");
971 else
972 { /* Alignment is already satisfied if the previous
973 * align value is greater. */
974 if ((sec->flags & ALIGN_DEFINED) && (value < sec->align))
975 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");
981 else
982 { sec->align = value; sec->flags |= ALIGN_DEFINED;
986 continue;
988 /* Handle valign attribute. */
989 case ATTRIB_VALIGN:
990 if (!value || ((value - 1) & value))
991 error(ERR_NONFATAL, "argument to `valign' is not a"
992 " power of two");
993 else
994 { /* Alignment is already satisfied if the previous
995 * align value is greater. */
996 if ((sec->flags & VALIGN_DEFINED) && (value < sec->valign))
997 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");
1003 else
1004 { sec->valign = value; sec->flags |= VALIGN_DEFINED;
1007 continue;
1009 /* Handle start attribute. */
1010 case ATTRIB_START:
1011 if (sec->flags & FOLLOWS_DEFINED)
1012 error(ERR_NONFATAL, "cannot combine `start' and `follows'"
1013 " section attributes");
1014 else if (value < 0)
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");
1019 else
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;
1028 continue;
1030 /* Handle vstart attribute. */
1031 case ATTRIB_VSTART:
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");
1038 else
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;
1047 continue;
1049 /* Handle follows attribute. */
1050 case ATTRIB_FOLLOWS:
1051 p = astring; astring += strcspn(astring, " \t");
1052 if (astring == p)
1053 error(ERR_NONFATAL, "expecting section name for `follows'"
1054 " attribute");
1055 else
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;
1063 continue;
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");
1070 else
1071 { p = astring; astring += strcspn(astring, " \t");
1072 if (astring == p)
1073 error(ERR_NONFATAL, "expecting section name for `vfollows'"
1074 " attribute");
1075 else
1076 { *(astring++) = '\0';
1077 sec->vfollows = nasm_strdup(p);
1078 sec->flags |= VFOLLOWS_DEFINED;
1081 continue;
1086 static void bin_define_section_labels()
1087 { static int labels_defined = 0;
1088 struct Section * sec;
1089 char * label_name;
1090 size_t base_len;
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);
1111 labels_defined = 1;
1114 static long bin_secname(char *name, int pass, int *bits)
1115 { char *p;
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).
1122 if (!name)
1123 { /* Reset ORG and section attributes at the start of each pass. */
1124 origin_defined = 0;
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. */
1133 *bits = 16;
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. */
1142 p = name;
1143 while (*p && !isspace(*p)) p++;
1144 if (*p) *p++ = '\0';
1145 sec = find_section_by_name(name);
1146 if(!sec)
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;
1170 #endif
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;
1183 expr *e;
1185 stdscan_reset();
1186 stdscan_bufptr = args;
1187 tokval.t_type = TOKEN_INVALID;
1188 e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
1189 if (e)
1190 { if (!is_really_simple(e))
1191 error(ERR_NONFATAL, "org value must be a critical"
1192 " expression");
1193 else
1194 { value = reloc_value(e);
1195 /* Check for ORG redefinition. */
1196 if (origin_defined && (value != origin))
1197 error(ERR_NONFATAL, "program origin redefined");
1198 else
1199 { origin = value;
1200 origin_defined = 1;
1204 else
1205 error(ERR_NONFATAL, "No or invalid offset specified"
1206 " in ORG directive.");
1207 return 1;
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"))
1213 { char *p;
1215 if (pass != 1) return 1;
1216 args += strspn(args, " \t");
1217 while (*args)
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;
1230 else if (!rf)
1231 { if (!nasm_stricmp(p, "stdout"))
1232 rf = stdout;
1233 else if (!nasm_stricmp(p, "stderr"))
1234 rf = stderr;
1235 else
1236 { /* Must be a filename. */
1237 rf = fopen(p, "wt");
1238 if (!rf)
1239 { error(ERR_WARNING, "unable to open map file `%s'", p);
1240 map_control = 0;
1241 return 1;
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;
1249 return 1;
1251 return 0;
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)
1260 { return segment;
1263 static int bin_set_info(enum geninfo type, char **val)
1264 { return 0;
1267 static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval)
1268 { fp = afp;
1269 error = errfunc;
1271 (void) eval; /* Don't warn that this parameter is unused. */
1272 (void) ldef; /* Placate optimizers. */
1274 relocs = NULL;
1275 reloctail = &relocs;
1276 origin_defined = 0;
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)",
1299 "bin",
1300 NULL,
1301 null_debug_arr,
1302 &null_debug_form,
1303 bin_stdmac,
1304 bin_init,
1305 bin_set_info,
1306 bin_out,
1307 bin_deflabel,
1308 bin_secname,
1309 bin_segbase,
1310 bin_directive,
1311 bin_filename,
1312 bin_cleanup
1315 /* This is needed for bin_define_section_labels() */
1316 struct ofmt *bin_get_ofmt()
1317 { return &of_bin;
1320 #endif /* #ifdef OF_BIN */