Mercurial > hg-old > index.cgi
annotate lwasm/output.c @ 404:0324fd09c7ac
Added documentation for the --symbol option for lwasm
author | lost@l-w.ca |
---|---|
date | Fri, 23 Jul 2010 18:31:33 -0600 |
parents | c94436adce83 |
children | 35a0b086bf4a |
rev | line source |
---|---|
339 | 1 /* |
2 output.c | |
374 | 3 Copyright © 2009, 2010 William Astle |
339 | 4 |
5 This file is part of LWASM. | |
6 | |
7 LWASM is free software: you can redistribute it and/or modify it under the | |
8 terms of the GNU General Public License as published by the Free Software | |
9 Foundation, either version 3 of the License, or (at your option) any later | |
10 version. | |
11 | |
12 This program is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 more details. | |
16 | |
17 You should have received a copy of the GNU General Public License along with | |
18 this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 | |
21 Contains the code for actually outputting the assembled code | |
22 */ | |
23 #include <config.h> | |
24 #include <errno.h> | |
25 #include <stdio.h> | |
26 #include <string.h> | |
27 #include <unistd.h> | |
374 | 28 |
29 #include <lw_alloc.h> | |
30 #include <lw_expr.h> | |
31 | |
339 | 32 #include "lwasm.h" |
33 | |
34 void write_code_raw(asmstate_t *as, FILE *of); | |
35 void write_code_decb(asmstate_t *as, FILE *of); | |
36 void write_code_rawrel(asmstate_t *as, FILE *of); | |
37 void write_code_obj(asmstate_t *as, FILE *of); | |
38 void write_code_os9(asmstate_t *as, FILE *of); | |
39 | |
40 // this prevents warnings about not using the return value of fwrite() | |
41 #define writebytes(s, l, c, f) do { int r; r = fwrite((s), (l), (c), (f)); } while (0) | |
42 | |
374 | 43 void do_output(asmstate_t *as) |
339 | 44 { |
45 FILE *of; | |
46 | |
47 if (as -> errorcount > 0) | |
48 { | |
49 fprintf(stderr, "Not doing output due to assembly errors.\n"); | |
50 return; | |
51 } | |
52 | |
374 | 53 of = fopen(as -> output_file, "wb"); |
339 | 54 if (!of) |
55 { | |
374 | 56 fprintf(stderr, "Cannot open '%s' for output", as -> output_file); |
339 | 57 perror(""); |
58 return; | |
59 } | |
60 | |
374 | 61 switch (as -> output_format) |
339 | 62 { |
63 case OUTPUT_RAW: | |
64 write_code_raw(as, of); | |
65 break; | |
66 | |
67 case OUTPUT_DECB: | |
68 write_code_decb(as, of); | |
69 break; | |
70 | |
71 case OUTPUT_RAWREL: | |
72 write_code_rawrel(as, of); | |
73 break; | |
74 | |
75 case OUTPUT_OBJ: | |
76 write_code_obj(as, of); | |
77 break; | |
78 | |
79 case OUTPUT_OS9: | |
80 write_code_os9(as, of); | |
81 break; | |
82 | |
83 default: | |
84 fprintf(stderr, "BUG: unrecognized output format when generating output file\n"); | |
85 fclose(of); | |
374 | 86 unlink(as -> output_file); |
339 | 87 return; |
88 } | |
89 | |
90 fclose(of); | |
91 } | |
92 | |
93 /* | |
94 rawrel output treats an ORG directive as an offset from the start of the | |
95 file. Undefined results will occur if an ORG directive moves the output | |
96 pointer backward. This particular implementation uses "fseek" to handle | |
97 ORG requests and to skip over RMBs. | |
98 | |
99 This simple brain damanged method simply does an fseek before outputting | |
100 each instruction. | |
101 */ | |
102 void write_code_rawrel(asmstate_t *as, FILE *of) | |
103 { | |
374 | 104 line_t *cl; |
339 | 105 |
374 | 106 for (cl = as -> line_head; cl; cl = cl -> next) |
339 | 107 { |
374 | 108 if (cl -> outputl <= 0) |
339 | 109 continue; |
110 | |
374 | 111 fseek(of, lw_expr_intval(cl -> addr), SEEK_SET); |
112 writebytes(cl -> output, cl -> outputl, 1, of); | |
339 | 113 } |
114 } | |
115 | |
116 /* | |
117 raw merely writes all the bytes directly to the file as is. ORG is just a | |
118 reference for the assembler to handle absolute references. Multiple ORG | |
119 statements will produce mostly useless results | |
120 */ | |
121 void write_code_raw(asmstate_t *as, FILE *of) | |
122 { | |
374 | 123 line_t *cl; |
339 | 124 |
374 | 125 for (cl = as -> line_head; cl; cl = cl -> next) |
339 | 126 { |
374 | 127 if (cl -> len > 0 && cl -> outputl == 0) |
339 | 128 { |
129 int i; | |
374 | 130 for (i = 0; i < cl -> len; i++) |
339 | 131 writebytes("\0", 1, 1, of); |
132 continue; | |
133 } | |
374 | 134 else if (cl -> outputl > 0) |
135 writebytes(cl -> output, cl -> outputl, 1, of); | |
339 | 136 } |
137 } | |
138 | |
139 | |
140 /* | |
141 OS9 target also just writes all the bytes in order. No need for anything | |
142 else. | |
143 */ | |
144 void write_code_os9(asmstate_t *as, FILE *of) | |
145 { | |
374 | 146 line_t *cl; |
339 | 147 |
374 | 148 for (cl = as -> line_head; cl; cl = cl -> next) |
339 | 149 { |
150 if (cl -> inmod == 0) | |
151 continue; | |
374 | 152 if (cl -> len > 0 && cl -> outputl == 0) |
339 | 153 { |
154 int i; | |
374 | 155 for (i = 0; i < cl -> len; i++) |
339 | 156 writebytes("\0", 1, 1, of); |
157 continue; | |
158 } | |
374 | 159 else if (cl -> outputl > 0) |
160 writebytes(cl -> output, cl -> outputl, 1, of); | |
339 | 161 } |
162 } | |
163 | |
164 void write_code_decb(asmstate_t *as, FILE *of) | |
165 { | |
166 long preambloc; | |
374 | 167 line_t *cl; |
339 | 168 int blocklen = -1; |
169 int nextcalc = -1; | |
170 unsigned char outbuf[5]; | |
374 | 171 int caddr; |
339 | 172 |
374 | 173 for (cl = as -> line_head; cl; cl = cl -> next) |
339 | 174 { |
374 | 175 if (cl -> outputl < 0) |
339 | 176 continue; |
374 | 177 caddr = lw_expr_intval(cl -> addr); |
178 if (caddr != nextcalc && cl -> outputl > 0) | |
339 | 179 { |
180 // need preamble here | |
181 if (blocklen > 0) | |
182 { | |
183 // update previous preamble if needed | |
184 fseek(of, preambloc, SEEK_SET); | |
185 outbuf[0] = (blocklen >> 8) & 0xFF; | |
186 outbuf[1] = blocklen & 0xFF; | |
187 writebytes(outbuf, 2, 1, of); | |
188 fseek(of, 0, SEEK_END); | |
189 } | |
190 blocklen = 0; | |
374 | 191 nextcalc = caddr; |
339 | 192 outbuf[0] = 0x00; |
193 outbuf[1] = 0x00; | |
194 outbuf[2] = 0x00; | |
195 outbuf[3] = (nextcalc >> 8) & 0xFF; | |
196 outbuf[4] = nextcalc & 0xFF; | |
197 preambloc = ftell(of) + 1; | |
198 writebytes(outbuf, 5, 1, of); | |
199 } | |
374 | 200 nextcalc += cl -> outputl; |
201 writebytes(cl -> output, cl -> outputl, 1, of); | |
202 blocklen += cl -> outputl; | |
339 | 203 } |
204 if (blocklen > 0) | |
205 { | |
206 fseek(of, preambloc, SEEK_SET); | |
207 outbuf[0] = (blocklen >> 8) & 0xFF; | |
208 outbuf[1] = blocklen & 0xFF; | |
209 writebytes(outbuf, 2, 1, of); | |
210 fseek(of, 0, SEEK_END); | |
211 } | |
212 | |
213 // now write postamble | |
214 outbuf[0] = 0xFF; | |
215 outbuf[1] = 0x00; | |
216 outbuf[2] = 0x00; | |
217 outbuf[3] = (as -> execaddr >> 8) & 0xFF; | |
218 outbuf[4] = (as -> execaddr) & 0xFF; | |
219 writebytes(outbuf, 5, 1, of); | |
220 } | |
221 | |
222 void write_code_obj_sbadd(sectiontab_t *s, unsigned char b) | |
223 { | |
224 if (s -> oblen >= s -> obsize) | |
225 { | |
374 | 226 s -> obytes = lw_realloc(s -> obytes, s -> obsize + 128); |
339 | 227 s -> obsize += 128; |
228 } | |
229 s -> obytes[s -> oblen] = b; | |
230 s -> oblen += 1; | |
231 } | |
232 | |
376 | 233 |
234 int write_code_obj_expraux(lw_expr_t e, void *of) | |
235 { | |
236 int tt; | |
237 int v; | |
238 unsigned char buf[16]; | |
239 | |
240 tt = lw_expr_type(e); | |
241 | |
242 switch (tt) | |
243 { | |
244 case lw_expr_type_oper: | |
245 buf[0] = 0x04; | |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
246 switch (lw_expr_whichop(e)) |
376 | 247 { |
248 case lw_expr_oper_plus: | |
249 buf[1] = 0x01; | |
250 break; | |
251 | |
252 case lw_expr_oper_minus: | |
253 buf[1] = 0x02; | |
254 break; | |
255 | |
256 case lw_expr_oper_times: | |
257 buf[1] = 0x03; | |
258 break; | |
259 | |
260 case lw_expr_oper_divide: | |
261 buf[1] = 0x04; | |
262 break; | |
263 | |
264 case lw_expr_oper_mod: | |
265 buf[1] = 0x05; | |
266 break; | |
267 | |
268 case lw_expr_oper_intdiv: | |
269 buf[1] = 0x06; | |
270 break; | |
271 | |
272 case lw_expr_oper_bwand: | |
273 buf[1] = 0x07; | |
274 break; | |
275 | |
276 case lw_expr_oper_bwor: | |
277 buf[1] = 0x08; | |
278 break; | |
279 | |
280 case lw_expr_oper_bwxor: | |
281 buf[1] = 0x09; | |
282 break; | |
283 | |
284 case lw_expr_oper_and: | |
285 buf[1] = 0x0A; | |
286 break; | |
287 | |
288 case lw_expr_oper_or: | |
289 buf[1] = 0x0B; | |
290 break; | |
291 | |
292 case lw_expr_oper_neg: | |
293 buf[1] = 0x0C; | |
294 break; | |
295 | |
296 case lw_expr_oper_com: | |
297 buf[1] = 0x0D; | |
298 break; | |
299 | |
300 default: | |
301 buf[1] = 0xff; | |
302 } | |
303 writebytes(buf, 2, 1, of); | |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
304 return 0; |
376 | 305 |
306 case lw_expr_type_int: | |
307 v = lw_expr_intval(e); | |
308 buf[0] = 0x01; | |
309 buf[1] = (v >> 8) & 0xff; | |
310 buf[2] = v & 0xff; | |
311 writebytes(buf, 3, 1, of); | |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
312 return 0; |
376 | 313 |
314 case lw_expr_type_special: | |
315 v = lw_expr_specint(e); | |
316 switch (v) | |
317 { | |
318 case lwasm_expr_secbase: | |
377
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
319 { |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
320 // replaced with a synthetic symbol |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
321 sectiontab_t *se; |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
322 se = lw_expr_specptr(e); |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
323 |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
324 writebytes("\x03\x02", 2, 1, of); |
377
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
325 writebytes(se -> name, strlen(se -> name) + 1, 1, of); |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
326 return 0; |
377
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
327 } |
376 | 328 case lwasm_expr_import: |
329 { | |
330 importlist_t *ie; | |
331 ie = lw_expr_specptr(e); | |
332 buf[0] = 0x02; | |
333 writebytes(buf, 1, 1, of); | |
334 writebytes(ie -> symbol, strlen(ie -> symbol) + 1, 1, of); | |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
335 return 0; |
376 | 336 } |
337 case lwasm_expr_syment: | |
338 { | |
339 struct symtabe *se; | |
340 se = lw_expr_specptr(e); | |
341 buf[0] = 0x03; | |
342 writebytes(buf, 1, 1, of); | |
343 writebytes(se -> symbol, strlen(se -> symbol), 1, of); | |
344 if (se -> context != -1) | |
345 { | |
346 sprintf(buf, "\x01%d", se -> context); | |
347 writebytes(buf, strlen(buf), 1, of); | |
348 } | |
349 writebytes("", 1, 1, of); | |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
350 return 0; |
376 | 351 } |
352 } | |
353 | |
354 default: | |
355 // unrecognized term type - replace with integer 0 | |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
356 // fprintf(stderr, "Unrecognized term type: %s\n", lw_expr_print(e)); |
376 | 357 buf[0] = 0x01; |
358 buf[1] = 0x00; | |
359 buf[2] = 0x00; | |
360 writebytes(buf, 3, 1, of); | |
361 break; | |
362 } | |
363 return 0; | |
364 } | |
365 | |
366 | |
339 | 367 void write_code_obj(asmstate_t *as, FILE *of) |
368 { | |
374 | 369 line_t *l; |
339 | 370 sectiontab_t *s; |
374 | 371 reloctab_t *re; |
375 | 372 exportlist_t *ex; |
374 | 373 struct symtabe *se; |
374 | |
339 | 375 int i; |
376 unsigned char buf[16]; | |
377 | |
378 // output the magic number and file header | |
379 // the 8 is NOT an error | |
380 writebytes("LWOBJ16", 8, 1, of); | |
381 | |
382 // run through the entire system and build the byte streams for each | |
383 // section; at the same time, generate a list of "local" symbols to | |
384 // output for each section | |
385 // NOTE: for "local" symbols, we will append \x01 and the ascii string | |
386 // of the context identifier (so sym in context 1 would be "sym\x011" | |
387 // we can do this because the linker can handle symbols with any | |
388 // character other than NUL. | |
389 // also we will generate a list of incomplete references for each | |
390 // section along with the actual definition that will be output | |
391 | |
392 // once all this information is generated, we will output each section | |
393 // to the file | |
394 | |
395 // NOTE: we build everything in memory then output it because the | |
396 // assembler accepts multiple instances of the same section but the | |
397 // linker expects only one instance of each section in the object file | |
398 // so we need to collect all the various pieces of a section together | |
399 // (also, the assembler treated multiple instances of the same section | |
400 // as continuations of previous sections so we would need to collect | |
401 // them together anyway. | |
402 | |
374 | 403 for (l = as -> line_head; l; l = l -> next) |
339 | 404 { |
374 | 405 if (l -> csect) |
339 | 406 { |
407 // we're in a section - need to output some bytes | |
374 | 408 if (l -> outputl > 0) |
409 for (i = 0; i < l -> outputl; i++) | |
410 write_code_obj_sbadd(l -> csect, l -> output[i]); | |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
411 else if (l -> outputl == 0 || l -> outputl == -1) |
374 | 412 for (i = 0; i < l -> len; i++) |
413 write_code_obj_sbadd(l -> csect, 0); | |
339 | 414 } |
415 } | |
416 | |
417 // run through the sections | |
418 for (s = as -> sections; s; s = s -> next) | |
419 { | |
420 // write the name | |
421 writebytes(s -> name, strlen(s -> name) + 1, 1, of); | |
422 | |
423 // write the flags | |
374 | 424 if (s -> flags & section_flag_bss) |
339 | 425 writebytes("\x01", 1, 1, of); |
426 | |
427 // indicate end of flags - the "" is NOT an error | |
428 writebytes("", 1, 1, of); | |
429 | |
430 // now the local symbols | |
377
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
431 |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
432 // a symbol for section base address |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
433 writebytes("\x02", 1, 1, of); |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
434 writebytes(s -> name, strlen(s -> name) + 1, 1, of); |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
435 // address 0; "\0" is not an error |
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
436 writebytes("\0", 2, 1, of); |
374 | 437 for (se = as -> symtab.head; se; se = se -> next) |
339 | 438 { |
393 | 439 lw_expr_t te; |
440 | |
441 debug_message(as, 200, "Consider symbol %s (%p) for export in section %p", se -> symbol, se -> section, s); | |
442 | |
339 | 443 // ignore symbols not in this section |
374 | 444 if (se -> section != s) |
339 | 445 continue; |
446 | |
393 | 447 debug_message(as, 200, " In section"); |
448 | |
374 | 449 if (se -> flags & symbol_flag_set) |
339 | 450 continue; |
451 | |
393 | 452 debug_message(as, 200, " Not symbol_flag_set"); |
453 | |
454 te = lw_expr_copy(se -> value); | |
455 debug_message(as, 200, " Value=%s", lw_expr_print(te)); | |
456 as -> exportcheck = 1; | |
457 as -> csect = s; | |
458 lwasm_reduce_expr(as, te); | |
459 as -> exportcheck = 0; | |
460 | |
461 debug_message(as, 200, " Value2=%s", lw_expr_print(te)); | |
462 | |
374 | 463 // don't output non-constant symbols |
393 | 464 if (!lw_expr_istype(te, lw_expr_type_int)) |
465 { | |
466 lw_expr_destroy(te); | |
339 | 467 continue; |
393 | 468 } |
374 | 469 |
470 writebytes(se -> symbol, strlen(se -> symbol), 1, of); | |
339 | 471 if (se -> context >= 0) |
472 { | |
473 writebytes("\x01", 1, 1, of); | |
474 sprintf(buf, "%d", se -> context); | |
475 writebytes(buf, strlen(buf), 1, of); | |
476 } | |
477 // the "" is NOT an error | |
478 writebytes("", 1, 1, of); | |
479 | |
480 // write the address | |
393 | 481 buf[0] = (lw_expr_intval(te) >> 8) & 0xff; |
482 buf[1] = lw_expr_intval(te) & 0xff; | |
339 | 483 writebytes(buf, 2, 1, of); |
393 | 484 lw_expr_destroy(te); |
339 | 485 } |
486 // flag end of local symbol table - "" is NOT an error | |
487 writebytes("", 1, 1, of); | |
488 | |
374 | 489 // now the exports -- FIXME |
375 | 490 for (ex = as -> exportlist; ex; ex = ex -> next) |
339 | 491 { |
374 | 492 int eval; |
375 | 493 lw_expr_t te; |
494 line_t tl; | |
495 | |
496 if (ex -> se -> section != s) | |
374 | 497 continue; |
375 | 498 te = lw_expr_copy(ex -> se -> value); |
499 as -> csect = ex -> se -> section; | |
500 as -> exportcheck = 1; | |
501 tl.as = as; | |
502 as -> cl = &tl; | |
503 lwasm_reduce_expr(as, te); | |
504 as -> exportcheck = 0; | |
505 as -> cl = NULL; | |
506 if (!lw_expr_istype(te, lw_expr_type_int)) | |
507 { | |
508 lw_expr_destroy(te); | |
374 | 509 continue; |
375 | 510 } |
511 eval = lw_expr_intval(te); | |
512 lw_expr_destroy(te); | |
374 | 513 writebytes(ex -> symbol, strlen(ex -> symbol) + 1, 1, of); |
514 buf[0] = (eval >> 8) & 0xff; | |
515 buf[1] = eval & 0xff; | |
339 | 516 writebytes(buf, 2, 1, of); |
517 } | |
375 | 518 |
339 | 519 // flag end of exported symbols - "" is NOT an error |
520 writebytes("", 1, 1, of); | |
521 | |
374 | 522 // FIXME - relocation table |
376 | 523 for (re = s -> reloctab; re; re = re -> next) |
339 | 524 { |
376 | 525 int offset; |
526 lw_expr_t te; | |
527 line_t tl; | |
528 | |
529 tl.as = as; | |
530 as -> cl = &tl; | |
531 as -> csect = s; | |
532 as -> exportcheck = 1; | |
533 | |
339 | 534 if (re -> expr == NULL) |
535 { | |
536 // this is an error but we'll simply ignore it | |
537 // and not output this expression | |
538 continue; | |
539 } | |
540 | |
541 // work through each term in the expression and output | |
542 // the proper equivalent to the object file | |
376 | 543 if (re -> size == 1) |
339 | 544 { |
545 // flag an 8 bit relocation (low 8 bits will be used) | |
546 buf[0] = 0xFF; | |
547 buf[1] = 0x01; | |
548 writebytes(buf, 2, 1, of); | |
549 } | |
376 | 550 |
387
a741d2e4869f
Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
lost@l-w.ca
parents:
377
diff
changeset
|
551 te = lw_expr_copy(re -> offset); |
376 | 552 lwasm_reduce_expr(as, te); |
553 if (!lw_expr_istype(te, lw_expr_type_int)) | |
339 | 554 { |
376 | 555 lw_expr_destroy(te); |
556 continue; | |
339 | 557 } |
376 | 558 offset = lw_expr_intval(te); |
559 lw_expr_destroy(te); | |
560 | |
561 // output expression | |
562 lw_expr_testterms(re -> expr, write_code_obj_expraux, of); | |
339 | 563 |
564 // flag end of expressions | |
565 writebytes("", 1, 1, of); | |
566 | |
567 // write the offset | |
376 | 568 buf[0] = (offset >> 8) & 0xff; |
569 buf[1] = offset & 0xff; | |
339 | 570 writebytes(buf, 2, 1, of); |
571 } | |
376 | 572 |
339 | 573 // flag end of incomplete references list |
574 writebytes("", 1, 1, of); | |
575 | |
576 // now blast out the code | |
577 | |
578 // length | |
579 buf[0] = s -> oblen >> 8 & 0xff; | |
580 buf[1] = s -> oblen & 0xff; | |
581 writebytes(buf, 2, 1, of); | |
582 | |
374 | 583 if (!(s -> flags & section_flag_bss)) |
339 | 584 { |
585 writebytes(s -> obytes, s -> oblen, 1, of); | |
586 } | |
587 } | |
588 | |
589 // flag no more sections | |
590 // the "" is NOT an error | |
591 writebytes("", 1, 1, of); | |
592 } |