Mercurial > hg-old > index.cgi
annotate lwasm/output.c @ 448:5cccf90bf838 3.0 tip
Fixed bug with complex external references generating invalid relocations in the object file
author | lost@l-w.ca |
---|---|
date | Fri, 05 Nov 2010 22:27:00 -0600 |
parents | 35a0b086bf4a |
children |
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; | |
448
5cccf90bf838
Fixed bug with complex external references generating invalid relocations in the object file
lost@l-w.ca
parents:
412
diff
changeset
|
238 int count = 1; |
376 | 239 unsigned char buf[16]; |
240 | |
241 tt = lw_expr_type(e); | |
242 | |
243 switch (tt) | |
244 { | |
245 case lw_expr_type_oper: | |
246 buf[0] = 0x04; | |
448
5cccf90bf838
Fixed bug with complex external references generating invalid relocations in the object file
lost@l-w.ca
parents:
412
diff
changeset
|
247 |
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
|
248 switch (lw_expr_whichop(e)) |
376 | 249 { |
250 case lw_expr_oper_plus: | |
251 buf[1] = 0x01; | |
448
5cccf90bf838
Fixed bug with complex external references generating invalid relocations in the object file
lost@l-w.ca
parents:
412
diff
changeset
|
252 count = lw_expr_operandcount(e) - 1; |
376 | 253 break; |
254 | |
255 case lw_expr_oper_minus: | |
256 buf[1] = 0x02; | |
257 break; | |
258 | |
259 case lw_expr_oper_times: | |
260 buf[1] = 0x03; | |
448
5cccf90bf838
Fixed bug with complex external references generating invalid relocations in the object file
lost@l-w.ca
parents:
412
diff
changeset
|
261 count = lw_expr_operandcount(e) - 1; |
376 | 262 break; |
263 | |
264 case lw_expr_oper_divide: | |
265 buf[1] = 0x04; | |
266 break; | |
267 | |
268 case lw_expr_oper_mod: | |
269 buf[1] = 0x05; | |
270 break; | |
271 | |
272 case lw_expr_oper_intdiv: | |
273 buf[1] = 0x06; | |
274 break; | |
275 | |
276 case lw_expr_oper_bwand: | |
277 buf[1] = 0x07; | |
278 break; | |
279 | |
280 case lw_expr_oper_bwor: | |
281 buf[1] = 0x08; | |
282 break; | |
283 | |
284 case lw_expr_oper_bwxor: | |
285 buf[1] = 0x09; | |
286 break; | |
287 | |
288 case lw_expr_oper_and: | |
289 buf[1] = 0x0A; | |
290 break; | |
291 | |
292 case lw_expr_oper_or: | |
293 buf[1] = 0x0B; | |
294 break; | |
295 | |
296 case lw_expr_oper_neg: | |
297 buf[1] = 0x0C; | |
298 break; | |
299 | |
300 case lw_expr_oper_com: | |
301 buf[1] = 0x0D; | |
302 break; | |
303 | |
304 default: | |
305 buf[1] = 0xff; | |
306 } | |
448
5cccf90bf838
Fixed bug with complex external references generating invalid relocations in the object file
lost@l-w.ca
parents:
412
diff
changeset
|
307 while (count--) |
5cccf90bf838
Fixed bug with complex external references generating invalid relocations in the object file
lost@l-w.ca
parents:
412
diff
changeset
|
308 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
|
309 return 0; |
376 | 310 |
311 case lw_expr_type_int: | |
312 v = lw_expr_intval(e); | |
313 buf[0] = 0x01; | |
314 buf[1] = (v >> 8) & 0xff; | |
315 buf[2] = v & 0xff; | |
316 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
|
317 return 0; |
376 | 318 |
319 case lw_expr_type_special: | |
320 v = lw_expr_specint(e); | |
321 switch (v) | |
322 { | |
323 case lwasm_expr_secbase: | |
377
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
324 { |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
325 // replaced with a synthetic symbol |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
326 sectiontab_t *se; |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
327 se = lw_expr_specptr(e); |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
328 |
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
|
329 writebytes("\x03\x02", 2, 1, of); |
377
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
330 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
|
331 return 0; |
377
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
332 } |
376 | 333 case lwasm_expr_import: |
334 { | |
335 importlist_t *ie; | |
336 ie = lw_expr_specptr(e); | |
337 buf[0] = 0x02; | |
338 writebytes(buf, 1, 1, of); | |
339 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
|
340 return 0; |
376 | 341 } |
342 case lwasm_expr_syment: | |
343 { | |
344 struct symtabe *se; | |
345 se = lw_expr_specptr(e); | |
346 buf[0] = 0x03; | |
347 writebytes(buf, 1, 1, of); | |
348 writebytes(se -> symbol, strlen(se -> symbol), 1, of); | |
349 if (se -> context != -1) | |
350 { | |
351 sprintf(buf, "\x01%d", se -> context); | |
352 writebytes(buf, strlen(buf), 1, of); | |
353 } | |
354 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
|
355 return 0; |
376 | 356 } |
357 } | |
358 | |
359 default: | |
360 // 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
|
361 // fprintf(stderr, "Unrecognized term type: %s\n", lw_expr_print(e)); |
376 | 362 buf[0] = 0x01; |
363 buf[1] = 0x00; | |
364 buf[2] = 0x00; | |
365 writebytes(buf, 3, 1, of); | |
366 break; | |
367 } | |
368 return 0; | |
369 } | |
370 | |
371 | |
339 | 372 void write_code_obj(asmstate_t *as, FILE *of) |
373 { | |
374 | 374 line_t *l; |
339 | 375 sectiontab_t *s; |
374 | 376 reloctab_t *re; |
375 | 377 exportlist_t *ex; |
374 | 378 struct symtabe *se; |
379 | |
339 | 380 int i; |
381 unsigned char buf[16]; | |
382 | |
383 // output the magic number and file header | |
384 // the 8 is NOT an error | |
385 writebytes("LWOBJ16", 8, 1, of); | |
386 | |
387 // run through the entire system and build the byte streams for each | |
388 // section; at the same time, generate a list of "local" symbols to | |
389 // output for each section | |
390 // NOTE: for "local" symbols, we will append \x01 and the ascii string | |
391 // of the context identifier (so sym in context 1 would be "sym\x011" | |
392 // we can do this because the linker can handle symbols with any | |
393 // character other than NUL. | |
394 // also we will generate a list of incomplete references for each | |
395 // section along with the actual definition that will be output | |
396 | |
397 // once all this information is generated, we will output each section | |
398 // to the file | |
399 | |
400 // NOTE: we build everything in memory then output it because the | |
401 // assembler accepts multiple instances of the same section but the | |
402 // linker expects only one instance of each section in the object file | |
403 // so we need to collect all the various pieces of a section together | |
404 // (also, the assembler treated multiple instances of the same section | |
405 // as continuations of previous sections so we would need to collect | |
406 // them together anyway. | |
407 | |
374 | 408 for (l = as -> line_head; l; l = l -> next) |
339 | 409 { |
374 | 410 if (l -> csect) |
339 | 411 { |
412 // we're in a section - need to output some bytes | |
374 | 413 if (l -> outputl > 0) |
414 for (i = 0; i < l -> outputl; i++) | |
415 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
|
416 else if (l -> outputl == 0 || l -> outputl == -1) |
374 | 417 for (i = 0; i < l -> len; i++) |
418 write_code_obj_sbadd(l -> csect, 0); | |
339 | 419 } |
420 } | |
421 | |
422 // run through the sections | |
423 for (s = as -> sections; s; s = s -> next) | |
424 { | |
425 // write the name | |
426 writebytes(s -> name, strlen(s -> name) + 1, 1, of); | |
427 | |
428 // write the flags | |
374 | 429 if (s -> flags & section_flag_bss) |
339 | 430 writebytes("\x01", 1, 1, of); |
431 | |
432 // indicate end of flags - the "" is NOT an error | |
433 writebytes("", 1, 1, of); | |
434 | |
435 // now the local symbols | |
377
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
436 |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
437 // a symbol for section base address |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
438 writebytes("\x02", 1, 1, of); |
55ed7d06b136
Fixed intersection internal references in object target
lost@starbug
parents:
376
diff
changeset
|
439 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
|
440 // 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
|
441 writebytes("\0", 2, 1, of); |
374 | 442 for (se = as -> symtab.head; se; se = se -> next) |
339 | 443 { |
393 | 444 lw_expr_t te; |
445 | |
446 debug_message(as, 200, "Consider symbol %s (%p) for export in section %p", se -> symbol, se -> section, s); | |
447 | |
339 | 448 // ignore symbols not in this section |
374 | 449 if (se -> section != s) |
339 | 450 continue; |
451 | |
393 | 452 debug_message(as, 200, " In section"); |
453 | |
374 | 454 if (se -> flags & symbol_flag_set) |
339 | 455 continue; |
456 | |
393 | 457 debug_message(as, 200, " Not symbol_flag_set"); |
458 | |
459 te = lw_expr_copy(se -> value); | |
460 debug_message(as, 200, " Value=%s", lw_expr_print(te)); | |
461 as -> exportcheck = 1; | |
462 as -> csect = s; | |
463 lwasm_reduce_expr(as, te); | |
464 as -> exportcheck = 0; | |
465 | |
466 debug_message(as, 200, " Value2=%s", lw_expr_print(te)); | |
467 | |
374 | 468 // don't output non-constant symbols |
393 | 469 if (!lw_expr_istype(te, lw_expr_type_int)) |
470 { | |
471 lw_expr_destroy(te); | |
339 | 472 continue; |
393 | 473 } |
374 | 474 |
475 writebytes(se -> symbol, strlen(se -> symbol), 1, of); | |
339 | 476 if (se -> context >= 0) |
477 { | |
478 writebytes("\x01", 1, 1, of); | |
479 sprintf(buf, "%d", se -> context); | |
480 writebytes(buf, strlen(buf), 1, of); | |
481 } | |
482 // the "" is NOT an error | |
483 writebytes("", 1, 1, of); | |
484 | |
485 // write the address | |
393 | 486 buf[0] = (lw_expr_intval(te) >> 8) & 0xff; |
487 buf[1] = lw_expr_intval(te) & 0xff; | |
339 | 488 writebytes(buf, 2, 1, of); |
393 | 489 lw_expr_destroy(te); |
339 | 490 } |
491 // flag end of local symbol table - "" is NOT an error | |
492 writebytes("", 1, 1, of); | |
493 | |
374 | 494 // now the exports -- FIXME |
375 | 495 for (ex = as -> exportlist; ex; ex = ex -> next) |
339 | 496 { |
374 | 497 int eval; |
375 | 498 lw_expr_t te; |
499 line_t tl; | |
500 | |
412
35a0b086bf4a
Added dummy .bank pseudo and fixed segfault in output for object target (on imported symbol)
lost@l-w.ca
parents:
393
diff
changeset
|
501 if (ex -> se == NULL) |
35a0b086bf4a
Added dummy .bank pseudo and fixed segfault in output for object target (on imported symbol)
lost@l-w.ca
parents:
393
diff
changeset
|
502 continue; |
375 | 503 if (ex -> se -> section != s) |
374 | 504 continue; |
375 | 505 te = lw_expr_copy(ex -> se -> value); |
506 as -> csect = ex -> se -> section; | |
507 as -> exportcheck = 1; | |
508 tl.as = as; | |
509 as -> cl = &tl; | |
510 lwasm_reduce_expr(as, te); | |
511 as -> exportcheck = 0; | |
512 as -> cl = NULL; | |
513 if (!lw_expr_istype(te, lw_expr_type_int)) | |
514 { | |
515 lw_expr_destroy(te); | |
374 | 516 continue; |
375 | 517 } |
518 eval = lw_expr_intval(te); | |
519 lw_expr_destroy(te); | |
374 | 520 writebytes(ex -> symbol, strlen(ex -> symbol) + 1, 1, of); |
521 buf[0] = (eval >> 8) & 0xff; | |
522 buf[1] = eval & 0xff; | |
339 | 523 writebytes(buf, 2, 1, of); |
524 } | |
375 | 525 |
339 | 526 // flag end of exported symbols - "" is NOT an error |
527 writebytes("", 1, 1, of); | |
528 | |
374 | 529 // FIXME - relocation table |
376 | 530 for (re = s -> reloctab; re; re = re -> next) |
339 | 531 { |
376 | 532 int offset; |
533 lw_expr_t te; | |
534 line_t tl; | |
535 | |
536 tl.as = as; | |
537 as -> cl = &tl; | |
538 as -> csect = s; | |
539 as -> exportcheck = 1; | |
540 | |
339 | 541 if (re -> expr == NULL) |
542 { | |
543 // this is an error but we'll simply ignore it | |
544 // and not output this expression | |
545 continue; | |
546 } | |
547 | |
548 // work through each term in the expression and output | |
549 // the proper equivalent to the object file | |
376 | 550 if (re -> size == 1) |
339 | 551 { |
552 // flag an 8 bit relocation (low 8 bits will be used) | |
553 buf[0] = 0xFF; | |
554 buf[1] = 0x01; | |
555 writebytes(buf, 2, 1, of); | |
556 } | |
376 | 557 |
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
|
558 te = lw_expr_copy(re -> offset); |
376 | 559 lwasm_reduce_expr(as, te); |
560 if (!lw_expr_istype(te, lw_expr_type_int)) | |
339 | 561 { |
376 | 562 lw_expr_destroy(te); |
563 continue; | |
339 | 564 } |
376 | 565 offset = lw_expr_intval(te); |
566 lw_expr_destroy(te); | |
567 | |
568 // output expression | |
569 lw_expr_testterms(re -> expr, write_code_obj_expraux, of); | |
339 | 570 |
571 // flag end of expressions | |
572 writebytes("", 1, 1, of); | |
573 | |
574 // write the offset | |
376 | 575 buf[0] = (offset >> 8) & 0xff; |
576 buf[1] = offset & 0xff; | |
339 | 577 writebytes(buf, 2, 1, of); |
578 } | |
376 | 579 |
339 | 580 // flag end of incomplete references list |
581 writebytes("", 1, 1, of); | |
582 | |
583 // now blast out the code | |
584 | |
585 // length | |
586 buf[0] = s -> oblen >> 8 & 0xff; | |
587 buf[1] = s -> oblen & 0xff; | |
588 writebytes(buf, 2, 1, of); | |
589 | |
374 | 590 if (!(s -> flags & section_flag_bss)) |
339 | 591 { |
592 writebytes(s -> obytes, s -> oblen, 1, of); | |
593 } | |
594 } | |
595 | |
596 // flag no more sections | |
597 // the "" is NOT an error | |
598 writebytes("", 1, 1, of); | |
599 } |