| 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 |