OLD | NEW |
1 /* | 1 /* |
2 * Win64 structured exception handling support | 2 * Win64 structured exception handling support |
3 * | 3 * |
4 * Copyright (C) 2007 Peter Johnson | 4 * Copyright (C) 2007 Peter Johnson |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
11 * 2. Redistributions in binary form must reproduce the above copyright | 11 * 2. Redistributions in binary form must reproduce the above copyright |
12 * notice, this list of conditions and the following disclaimer in the | 12 * notice, this list of conditions and the following disclaimer in the |
13 * documentation and/or other materials provided with the distribution. | 13 * documentation and/or other materials provided with the distribution. |
14 * | 14 * |
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' | 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' |
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE | 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE |
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * POSSIBILITY OF SUCH DAMAGE. | 25 * POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 #include <util.h> | 27 #include <util.h> |
28 /*@unused@*/ RCSID("$Id: win64-except.c 2130 2008-10-07 05:38:11Z peter $"); | |
29 | 28 |
30 #include <libyasm.h> | 29 #include <libyasm.h> |
31 | 30 |
32 #include "coff-objfmt.h" | 31 #include "coff-objfmt.h" |
33 | 32 |
34 | 33 |
35 #define UNW_FLAG_EHANDLER 0x01 | 34 #define UNW_FLAG_EHANDLER 0x01 |
36 #define UNW_FLAG_UHANDLER 0x02 | 35 #define UNW_FLAG_UHANDLER 0x02 |
37 #define UNW_FLAG_CHAININFO 0x04 | 36 #define UNW_FLAG_CHAININFO 0x04 |
38 | 37 |
39 /* Bytecode callback function prototypes */ | 38 /* Bytecode callback function prototypes */ |
40 static void win64_uwinfo_bc_destroy(void *contents); | 39 static void win64_uwinfo_bc_destroy(void *contents); |
41 static void win64_uwinfo_bc_print(const void *contents, FILE *f, | 40 static void win64_uwinfo_bc_print(const void *contents, FILE *f, |
42 int indent_level); | 41 int indent_level); |
43 static void win64_uwinfo_bc_finalize(yasm_bytecode *bc, | 42 static void win64_uwinfo_bc_finalize(yasm_bytecode *bc, |
44 yasm_bytecode *prev_bc); | 43 yasm_bytecode *prev_bc); |
45 static int win64_uwinfo_bc_calc_len | 44 static int win64_uwinfo_bc_calc_len |
46 (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); | 45 (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); |
47 static int win64_uwinfo_bc_expand(yasm_bytecode *bc, int span, long old_val, | 46 static int win64_uwinfo_bc_expand(yasm_bytecode *bc, int span, long old_val, |
48 long new_val, /*@out@*/ long *neg_thres, | 47 long new_val, /*@out@*/ long *neg_thres, |
49 /*@out@*/ long *pos_thres); | 48 /*@out@*/ long *pos_thres); |
50 static int win64_uwinfo_bc_tobytes | 49 static int win64_uwinfo_bc_tobytes |
51 (yasm_bytecode *bc, unsigned char **bufp, void *d, | 50 (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, |
52 yasm_output_value_func output_value, | 51 yasm_output_value_func output_value, |
53 /*@null@*/ yasm_output_reloc_func output_reloc); | 52 /*@null@*/ yasm_output_reloc_func output_reloc); |
54 | 53 |
55 static void win64_uwcode_bc_destroy(void *contents); | 54 static void win64_uwcode_bc_destroy(void *contents); |
56 static void win64_uwcode_bc_print(const void *contents, FILE *f, | 55 static void win64_uwcode_bc_print(const void *contents, FILE *f, |
57 int indent_level); | 56 int indent_level); |
58 static void win64_uwcode_bc_finalize(yasm_bytecode *bc, | 57 static void win64_uwcode_bc_finalize(yasm_bytecode *bc, |
59 yasm_bytecode *prev_bc); | 58 yasm_bytecode *prev_bc); |
60 static int win64_uwcode_bc_calc_len | 59 static int win64_uwcode_bc_calc_len |
61 (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); | 60 (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); |
62 static int win64_uwcode_bc_expand(yasm_bytecode *bc, int span, long old_val, | 61 static int win64_uwcode_bc_expand(yasm_bytecode *bc, int span, long old_val, |
63 long new_val, /*@out@*/ long *neg_thres, | 62 long new_val, /*@out@*/ long *neg_thres, |
64 /*@out@*/ long *pos_thres); | 63 /*@out@*/ long *pos_thres); |
65 static int win64_uwcode_bc_tobytes | 64 static int win64_uwcode_bc_tobytes |
66 (yasm_bytecode *bc, unsigned char **bufp, void *d, | 65 (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, |
67 yasm_output_value_func output_value, | 66 yasm_output_value_func output_value, |
68 /*@null@*/ yasm_output_reloc_func output_reloc); | 67 /*@null@*/ yasm_output_reloc_func output_reloc); |
69 | 68 |
70 /* Bytecode callback structures */ | 69 /* Bytecode callback structures */ |
71 static const yasm_bytecode_callback win64_uwinfo_bc_callback = { | 70 static const yasm_bytecode_callback win64_uwinfo_bc_callback = { |
72 win64_uwinfo_bc_destroy, | 71 win64_uwinfo_bc_destroy, |
73 win64_uwinfo_bc_print, | 72 win64_uwinfo_bc_print, |
74 win64_uwinfo_bc_finalize, | 73 win64_uwinfo_bc_finalize, |
75 NULL, | 74 NULL, |
76 win64_uwinfo_bc_calc_len, | 75 win64_uwinfo_bc_calc_len, |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 N_("frame offset of %ld bytes, must be between 0 and 240"), | 271 N_("frame offset of %ld bytes, must be between 0 and 240"), |
273 new_val); | 272 new_val); |
274 return -1; | 273 return -1; |
275 default: | 274 default: |
276 yasm_internal_error(N_("unrecognized span id")); | 275 yasm_internal_error(N_("unrecognized span id")); |
277 } | 276 } |
278 return 0; | 277 return 0; |
279 } | 278 } |
280 | 279 |
281 static int | 280 static int |
282 win64_uwinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, | 281 win64_uwinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, |
| 282 unsigned char *bufstart, void *d, |
283 yasm_output_value_func output_value, | 283 yasm_output_value_func output_value, |
284 yasm_output_reloc_func output_reloc) | 284 yasm_output_reloc_func output_reloc) |
285 { | 285 { |
286 coff_unwind_info *info = (coff_unwind_info *)bc->contents; | 286 coff_unwind_info *info = (coff_unwind_info *)bc->contents; |
287 unsigned char *buf = *bufp; | 287 unsigned char *buf = *bufp; |
288 /*@only@*/ /*@null@*/ yasm_intnum *frameoff; | 288 /*@only@*/ /*@null@*/ yasm_intnum *frameoff; |
289 long intv; | 289 long intv; |
290 | 290 |
291 /* Version and flags */ | 291 /* Version and flags */ |
292 if (info->ehandler) | 292 if (info->ehandler) |
293 YASM_WRITE_8(buf, 1 | (UNW_FLAG_EHANDLER << 3)); | 293 YASM_WRITE_8(buf, 1 | (UNW_FLAG_EHANDLER << 3)); |
294 else | 294 else |
295 YASM_WRITE_8(buf, 1); | 295 YASM_WRITE_8(buf, 1); |
296 | 296 |
297 /* Size of prolog */ | 297 /* Size of prolog */ |
298 output_value(&info->prolog_size, buf, 1, (unsigned long)(buf-*bufp), | 298 output_value(&info->prolog_size, buf, 1, (unsigned long)(buf-bufstart), |
299 bc, 1, d); | 299 bc, 1, d); |
300 buf += 1; | 300 buf += 1; |
301 | 301 |
302 /* Count of codes */ | 302 /* Count of codes */ |
303 output_value(&info->codes_count, buf, 1, (unsigned long)(buf-*bufp), | 303 output_value(&info->codes_count, buf, 1, (unsigned long)(buf-bufstart), |
304 bc, 1, d); | 304 bc, 1, d); |
305 buf += 1; | 305 buf += 1; |
306 | 306 |
307 /* Frame register and offset */ | 307 /* Frame register and offset */ |
308 frameoff = yasm_value_get_intnum(&info->frameoff, bc, 1); | 308 frameoff = yasm_value_get_intnum(&info->frameoff, bc, 1); |
309 if (!frameoff) { | 309 if (!frameoff) { |
310 yasm_error_set(YASM_ERROR_VALUE, | 310 yasm_error_set(YASM_ERROR_VALUE, |
311 N_("frame offset expression too complex")); | 311 N_("frame offset expression too complex")); |
312 return 1; | 312 return 1; |
313 } | 313 } |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 code->opcode = UWOP_SAVE_NONVOL_FAR; | 452 code->opcode = UWOP_SAVE_NONVOL_FAR; |
453 bc->len += 2; | 453 bc->len += 2; |
454 } else if (code->opcode == UWOP_SAVE_XMM128 && span == 3) { | 454 } else if (code->opcode == UWOP_SAVE_XMM128 && span == 3) { |
455 code->opcode = UWOP_SAVE_XMM128_FAR; | 455 code->opcode = UWOP_SAVE_XMM128_FAR; |
456 bc->len += 2; | 456 bc->len += 2; |
457 } | 457 } |
458 return 0; | 458 return 0; |
459 } | 459 } |
460 | 460 |
461 static int | 461 static int |
462 win64_uwcode_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, | 462 win64_uwcode_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, |
| 463 unsigned char *bufstart, void *d, |
463 yasm_output_value_func output_value, | 464 yasm_output_value_func output_value, |
464 yasm_output_reloc_func output_reloc) | 465 yasm_output_reloc_func output_reloc) |
465 { | 466 { |
466 coff_unwind_code *code = (coff_unwind_code *)bc->contents; | 467 coff_unwind_code *code = (coff_unwind_code *)bc->contents; |
467 unsigned char *buf = *bufp; | 468 unsigned char *buf = *bufp; |
468 yasm_value val; | 469 yasm_value val; |
469 unsigned int size; | 470 unsigned int size; |
470 int shift; | 471 int shift; |
471 long intv, low, high, mask; | 472 long intv, low, high, mask; |
472 yasm_intnum *intn; | 473 yasm_intnum *intn; |
473 | 474 |
474 /* Offset in prolog */ | 475 /* Offset in prolog */ |
475 yasm_value_initialize(&val, | 476 yasm_value_initialize(&val, |
476 yasm_expr_create(YASM_EXPR_SUB, yasm_expr_sym(code->loc), | 477 yasm_expr_create(YASM_EXPR_SUB, yasm_expr_sym(code->loc), |
477 yasm_expr_sym(code->proc), bc->line), | 478 yasm_expr_sym(code->proc), bc->line), |
478 8); | 479 8); |
479 output_value(&val, buf, 1, (unsigned long)(buf-*bufp), bc, 1, d); | 480 output_value(&val, buf, 1, (unsigned long)(buf-bufstart), bc, 1, d); |
480 buf += 1; | 481 buf += 1; |
481 yasm_value_delete(&val); | 482 yasm_value_delete(&val); |
482 | 483 |
483 /* Offset value */ | 484 /* Offset value */ |
484 switch (code->opcode) { | 485 switch (code->opcode) { |
485 case UWOP_PUSH_NONVOL: | 486 case UWOP_PUSH_NONVOL: |
486 case UWOP_SET_FPREG: | 487 case UWOP_SET_FPREG: |
487 case UWOP_PUSH_MACHFRAME: | 488 case UWOP_PUSH_MACHFRAME: |
488 /* just 1 node, no offset; write opcode and info and we're done */ | 489 /* just 1 node, no offset; write opcode and info and we're done */ |
489 YASM_WRITE_8(buf, (code->info << 4) | (code->opcode & 0xF)); | 490 YASM_WRITE_8(buf, (code->info << 4) | (code->opcode & 0xF)); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 if (size != 0) { | 550 if (size != 0) { |
550 yasm_intnum_get_sized(intn, buf, size, size*8, -shift, 0, 1); | 551 yasm_intnum_get_sized(intn, buf, size, size*8, -shift, 0, 1); |
551 buf += size; | 552 buf += size; |
552 } | 553 } |
553 | 554 |
554 yasm_intnum_destroy(intn); | 555 yasm_intnum_destroy(intn); |
555 | 556 |
556 *bufp = buf; | 557 *bufp = buf; |
557 return 0; | 558 return 0; |
558 } | 559 } |
OLD | NEW |