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