]> git.saurik.com Git - apple/boot.git/blob - i386/nasm/outbin.c
boot-132.tar.gz
[apple/boot.git] / i386 / nasm / outbin.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /* outbin.c output routines for the Netwide Assembler to produce
25 * flat-form binary files
26 *
27 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
28 * Julian Hall. All rights reserved. The software is
29 * redistributable under the licence given in the file "Licence"
30 * distributed in the NASM archive.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "nasm.h"
39 #include "nasmlib.h"
40 #include "outform.h"
41
42 #ifdef OF_BIN
43
44 static FILE *fp;
45 static efunc error;
46
47 static struct Section {
48 struct SAA *contents;
49 long length;
50 long index;
51 } textsect, datasect;
52 static long bsslen, bssindex;
53
54 static struct Reloc {
55 struct Reloc *next;
56 long posn;
57 long bytes;
58 long secref;
59 long secrel;
60 struct Section *target;
61 } *relocs, **reloctail;
62
63 static long data_align, bss_align;
64
65 static long start_point;
66
67 static void add_reloc (struct Section *s, long bytes, long secref,
68 long secrel) {
69 struct Reloc *r;
70
71 r = *reloctail = nasm_malloc(sizeof(struct Reloc));
72 reloctail = &r->next;
73 r->next = NULL;
74 r->posn = s->length;
75 r->bytes = bytes;
76 r->secref = secref;
77 r->secrel = secrel;
78 r->target = s;
79 }
80
81 static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval) {
82 fp = afp;
83
84 error = errfunc;
85 (void) ldef; /* placate optimisers */
86
87 start_point = 0L; /* default */
88 textsect.contents = saa_init(1L);
89 datasect.contents = saa_init(1L);
90 textsect.length = datasect.length = 0;
91 textsect.index = seg_alloc();
92 datasect.index = seg_alloc();
93 bsslen = 0;
94 bssindex = seg_alloc();
95 relocs = NULL;
96 reloctail = &relocs;
97 data_align = bss_align = 4;
98 }
99
100 static void bin_cleanup (void) {
101 struct Reloc *r;
102 long datapos, datagap, bsspos;
103
104 datapos = start_point + textsect.length;
105 datapos = (datapos + data_align-1) & ~(data_align-1);
106 datagap = datapos - (start_point + textsect.length);
107 bsspos = datapos + datasect.length;
108 bsspos = (bsspos + bss_align-1) & ~(bss_align-1);
109
110 saa_rewind (textsect.contents);
111 saa_rewind (datasect.contents);
112
113 for (r = relocs; r; r = r->next) {
114 unsigned char *p, *q, mydata[4];
115 long l;
116
117 saa_fread (r->target->contents, r->posn, mydata, r->bytes);
118 p = q = mydata;
119 l = *p++;
120 if (r->bytes > 1) {
121 l += ((long)*p++) << 8;
122 if (r->bytes == 4) {
123 l += ((long)*p++) << 16;
124 l += ((long)*p++) << 24;
125 }
126 }
127
128 if (r->secref == textsect.index)
129 l += start_point;
130 else if (r->secref == datasect.index)
131 l += datapos;
132 else if (r->secref == bssindex)
133 l += bsspos;
134
135 if (r->secrel == textsect.index)
136 l -= start_point;
137 else if (r->secrel == datasect.index)
138 l -= datapos;
139 else if (r->secrel == bssindex)
140 l -= bsspos;
141
142 if (r->bytes == 4)
143 WRITELONG(q, l);
144 else if (r->bytes == 2)
145 WRITESHORT(q, l);
146 else
147 *q++ = l & 0xFF;
148 saa_fwrite (r->target->contents, r->posn, mydata, r->bytes);
149 }
150 saa_fpwrite (textsect.contents, fp);
151 if (datasect.length > 0) {
152 while (datagap--)
153 fputc('\0', fp);
154 saa_fpwrite (datasect.contents, fp);
155 }
156 fclose (fp);
157 saa_free (textsect.contents);
158 saa_free (datasect.contents);
159 while (relocs) {
160 r = relocs->next;
161 nasm_free (relocs);
162 relocs = r;
163 }
164 }
165
166 static void bin_out (long segto, void *data, unsigned long type,
167 long segment, long wrt) {
168 unsigned char *p, mydata[4];
169 struct Section *s;
170 long realbytes;
171
172 if (wrt != NO_SEG) {
173 wrt = NO_SEG; /* continue to do _something_ */
174 error (ERR_NONFATAL, "WRT not supported by binary output format");
175 }
176
177 /*
178 * handle absolute-assembly (structure definitions)
179 */
180 if (segto == NO_SEG) {
181 if ((type & OUT_TYPMASK) != OUT_RESERVE)
182 error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
183 " space");
184 return;
185 }
186
187 if (segto == bssindex) { /* BSS */
188 if ((type & OUT_TYPMASK) != OUT_RESERVE)
189 error(ERR_WARNING, "attempt to initialise memory in the"
190 " BSS section: ignored");
191 s = NULL;
192 } else if (segto == textsect.index) {
193 s = &textsect;
194 } else if (segto == datasect.index) {
195 s = &datasect;
196 } else {
197 error(ERR_WARNING, "attempt to assemble code in"
198 " segment %d: defaulting to `.text'", segto);
199 s = &textsect;
200 }
201
202 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
203 if (segment != NO_SEG &&
204 segment != textsect.index &&
205 segment != datasect.index &&
206 segment != bssindex) {
207 if (segment % 2)
208 error(ERR_NONFATAL, "binary output format does not support"
209 " segment base references");
210 else
211 error(ERR_NONFATAL, "binary output format does not support"
212 " external references");
213 segment = NO_SEG;
214 }
215 if (s) {
216 if (segment != NO_SEG)
217 add_reloc (s, type & OUT_SIZMASK, segment, -1L);
218 p = mydata;
219 if ((type & OUT_SIZMASK) == 4)
220 WRITELONG (p, *(long *)data);
221 else
222 WRITESHORT (p, *(long *)data);
223 saa_wbytes (s->contents, mydata, type & OUT_SIZMASK);
224 s->length += type & OUT_SIZMASK;
225 } else
226 bsslen += type & OUT_SIZMASK;
227 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
228 type &= OUT_SIZMASK;
229 p = data;
230 if (s) {
231 saa_wbytes (s->contents, data, type);
232 s->length += type;
233 } else
234 bsslen += type;
235 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
236 if (s) {
237 error(ERR_WARNING, "uninitialised space declared in"
238 " %s section: zeroing",
239 (segto == textsect.index ? "code" : "data"));
240 }
241 type &= OUT_SIZMASK;
242 if (s) {
243 saa_wbytes (s->contents, NULL, type);
244 s->length += type;
245 } else
246 bsslen += type;
247 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
248 (type & OUT_TYPMASK) == OUT_REL4ADR) {
249 realbytes = ((type & OUT_TYPMASK) == OUT_REL4ADR ? 4 : 2);
250 if (segment != NO_SEG &&
251 segment != textsect.index &&
252 segment != datasect.index &&
253 segment != bssindex) {
254 if (segment % 2)
255 error(ERR_NONFATAL, "binary output format does not support"
256 " segment base references");
257 else
258 error(ERR_NONFATAL, "binary output format does not support"
259 " external references");
260 segment = NO_SEG;
261 }
262 if (s) {
263 add_reloc (s, realbytes, segment, segto);
264 p = mydata;
265 if (realbytes == 4)
266 WRITELONG (p, *(long*)data - realbytes - s->length);
267 else
268 WRITESHORT (p, *(long*)data - realbytes - s->length);
269 saa_wbytes (s->contents, mydata, realbytes);
270 s->length += realbytes;
271 } else
272 bsslen += realbytes;
273 }
274 }
275
276 static void bin_deflabel (char *name, long segment, long offset,
277 int is_global, char *special) {
278
279 if (special)
280 error (ERR_NONFATAL, "binary format does not support any"
281 " special symbol types");
282
283 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
284 error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
285 return;
286 }
287
288 if (is_global == 2) {
289 error (ERR_NONFATAL, "binary output format does not support common"
290 " variables");
291 }
292 }
293
294 static long bin_secname (char *name, int pass, int *bits) {
295 int sec_index;
296 long *sec_align;
297 char *p;
298
299 /*
300 * Default is 16 bits.
301 */
302 if (!name)
303 *bits = 16;
304
305 if (!name)
306 return textsect.index;
307
308 p = name;
309 while (*p && !isspace(*p)) p++;
310 if (*p) *p++ = '\0';
311 if (!strcmp(name, ".text")) {
312 sec_index = textsect.index;
313 sec_align = NULL;
314 } else if (!strcmp(name, ".data")) {
315 sec_index = datasect.index;
316 sec_align = &data_align;
317 } else if (!strcmp(name, ".bss")) {
318 sec_index = bssindex;
319 sec_align = &bss_align;
320 } else
321 return NO_SEG;
322
323 if (*p) {
324 if (!nasm_strnicmp(p,"align=",6)) {
325 if (sec_align == NULL)
326 error(ERR_NONFATAL, "cannot specify an alignment to"
327 " the `.text' section");
328 else if (p[6+strspn(p+6,"0123456789")])
329 error(ERR_NONFATAL, "argument to `align' is not numeric");
330 else {
331 unsigned int align = atoi(p+6);
332 if (!align || ((align-1) & align))
333 error(ERR_NONFATAL, "argument to `align' is not a"
334 " power of two");
335 else
336 *sec_align = align;
337 }
338 }
339 }
340
341 return sec_index;
342 }
343
344 static long bin_segbase (long segment) {
345 return segment;
346 }
347
348 static int bin_directive (char *directive, char *value, int pass) {
349 int rn_error;
350
351 if (!strcmp(directive, "org")) {
352 start_point = readnum (value, &rn_error);
353 if (rn_error)
354 error (ERR_NONFATAL, "argument to ORG should be numeric");
355 return 1;
356 } else
357 return 0;
358 }
359
360 static void bin_filename (char *inname, char *outname, efunc error) {
361 standard_extension (inname, outname, "", error);
362 }
363
364 static char *bin_stdmac[] = {
365 "%define __SECT__ [section .text]",
366 "%imacro org 1+.nolist",
367 "[org %1]",
368 "%endmacro",
369 NULL
370 };
371
372 struct ofmt of_bin = {
373 "flat-form binary files (e.g. DOS .COM, .SYS)",
374 "bin",
375 bin_stdmac,
376 bin_init,
377 bin_out,
378 bin_deflabel,
379 bin_secname,
380 bin_segbase,
381 bin_directive,
382 bin_filename,
383 bin_cleanup
384 };
385
386 #endif /* OF_BIN */