?? x86bc.c
字號:
/* * x86 bytecode utility functions * * Copyright (C) 2001 Peter Johnson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include <util.h>/*@unused@*/ RCSID("$Id: x86bc.c 1168 2004-10-31 01:07:52Z peter $");#define YASM_LIB_INTERNAL#define YASM_BC_INTERNAL#define YASM_EXPR_INTERNAL#include <libyasm.h>#include "x86arch.h"/* Effective address type */typedef struct x86_effaddr { yasm_effaddr ea; /* base structure */ /* PC-relative portions are for AMD64 only (RIP addressing) */ /*@null@*/ /*@dependent@*/ yasm_symrec *origin; /* pcrel origin */ unsigned char segment; /* segment override, 0 if none */ /* How the spare (register) bits in Mod/RM are handled: * Even if valid_modrm=0, the spare bits are still valid (don't overwrite!) * They're set in bytecode_create_insn(). */ unsigned char modrm; unsigned char valid_modrm; /* 1 if Mod/RM byte currently valid, 0 if not */ unsigned char need_modrm; /* 1 if Mod/RM byte needed, 0 if not */ unsigned char sib; unsigned char valid_sib; /* 1 if SIB byte currently valid, 0 if not */ unsigned char need_sib; /* 1 if SIB byte needed, 0 if not, 0xff if unknown */ unsigned char pcrel; /* 1 if PC-relative transformation needed */} x86_effaddr;/* Bytecode types */typedef struct x86_insn { yasm_bytecode bc; /* base structure */ /*@null@*/ x86_effaddr *ea; /* effective address */ /*@null@*/ yasm_immval *imm;/* immediate or relative value */ unsigned char opcode[3]; /* opcode */ unsigned char opcode_len; unsigned char addrsize; /* 0 or =mode_bits => no override */ unsigned char opersize; /* 0 or =mode_bits => no override */ unsigned char lockrep_pre; /* 0 indicates no prefix */ unsigned char def_opersize_64; /* default operand size in 64-bit mode */ unsigned char special_prefix; /* "special" prefix (0=none) */ unsigned char rex; /* REX AMD64 extension, 0 if none, 0xff if not allowed (high 8 bit reg used) */ /* HACK, but a space-saving one: shift opcodes have an immediate * form and a ,1 form (with no immediate). In the parser, we * set this and opcode_len=1, but store the ,1 version in the * second byte of the opcode array. We then choose between the * two versions once we know the actual value of imm (because we * don't know it in the parser module). * * A override to force the imm version should just leave this at * 0. Then later code won't know the ,1 version even exists. * TODO: Figure out how this affects CPU flags processing. * * Call x86_SetInsnShiftFlag() to set this flag to 1. */ unsigned char shift_op; /* HACK, similar to that for shift_op above, for optimizing instructions * that take a sign-extended imm8 as well as imm values (eg, the arith * instructions and a subset of the imul instructions). */ unsigned char signext_imm8_op; /* HACK, similar to those above, for optimizing long (modrm+sib) mov * instructions in amd64 into short mov instructions if a 32-bit address * override is applied in 64-bit mode to an EA of just an offset (no * registers) and the target register is al/ax/eax/rax. */ unsigned char shortmov_op; unsigned char mode_bits;} x86_insn;typedef struct x86_jmp { yasm_bytecode bc; /* base structure */ yasm_expr *target; /* target location */ /*@dependent@*/ yasm_symrec *origin; /* jump origin */ struct { unsigned char opcode[3]; unsigned char opcode_len; /* 0 = no opc for this version */ } shortop, nearop, farop; /* which opcode are we using? */ /* The *FORCED forms are specified in the source as such */ x86_jmp_opcode_sel op_sel; unsigned char addrsize; /* 0 or =mode_bits => no override */ unsigned char opersize; /* 0 indicates no override */ unsigned char lockrep_pre; /* 0 indicates no prefix */ unsigned char mode_bits;} x86_jmp;/* Effective address callback function prototypes */static void x86_ea_destroy(yasm_effaddr *ea);static void x86_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level);/* Bytecode callback function prototypes */static void x86_bc_insn_destroy(yasm_bytecode *bc);static void x86_bc_insn_print(const yasm_bytecode *bc, FILE *f, int indent_level);static yasm_bc_resolve_flags x86_bc_insn_resolve (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);static int x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, yasm_output_expr_func output_expr, /*@null@*/ yasm_output_reloc_func output_reloc);static void x86_bc_jmp_destroy(yasm_bytecode *bc);static void x86_bc_jmp_print(const yasm_bytecode *bc, FILE *f, int indent_level);static yasm_bc_resolve_flags x86_bc_jmp_resolve (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);static int x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, yasm_output_expr_func output_expr, /*@null@*/ yasm_output_reloc_func output_reloc);/* Effective address callback structures */static const yasm_effaddr_callback x86_ea_callback = { x86_ea_destroy, x86_ea_print};/* Bytecode callback structures */static const yasm_bytecode_callback x86_bc_callback_insn = { x86_bc_insn_destroy, x86_bc_insn_print, x86_bc_insn_resolve, x86_bc_insn_tobytes};static const yasm_bytecode_callback x86_bc_callback_jmp = { x86_bc_jmp_destroy, x86_bc_jmp_print, x86_bc_jmp_resolve, x86_bc_jmp_tobytes};intyasm_x86__set_rex_from_reg(unsigned char *rex, unsigned char *low3, unsigned long reg, unsigned int bits, x86_rex_bit_pos rexbit){ *low3 = (unsigned char)(reg&7); if (bits == 64) { x86_expritem_reg_size size = (x86_expritem_reg_size)(reg & ~0xFUL); if (size == X86_REG8X || (reg & 0xF) >= 8) { if (*rex == 0xff) return 1; *rex |= 0x40 | (((reg & 8) >> 3) << rexbit); } else if (size == X86_REG8 && (reg & 7) >= 4) { /* AH/BH/CH/DH, so no REX allowed */ if (*rex != 0 && *rex != 0xff) return 1; *rex = 0xff; } } return 0;}/*@-compmempass -mustfree@*/yasm_bytecode *yasm_x86__bc_create_insn(yasm_arch *arch, x86_new_insn_data *d){ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; x86_insn *insn; insn = (x86_insn *)yasm_bc_create_common(&x86_bc_callback_insn, sizeof(x86_insn), d->line); insn->ea = (x86_effaddr *)d->ea; if (d->ea) { insn->ea->origin = d->ea_origin; insn->ea->modrm &= 0xC7; /* zero spare/reg bits */ insn->ea->modrm |= (d->spare << 3) & 0x38; /* plug in provided bits */ } if (d->imm) { insn->imm = yasm_imm_create_expr(d->imm); insn->imm->len = d->im_len; insn->imm->sign = d->im_sign; } else insn->imm = NULL; insn->opcode[0] = d->op[0]; insn->opcode[1] = d->op[1]; insn->opcode[2] = d->op[2]; insn->opcode_len = d->op_len; insn->addrsize = 0; insn->opersize = d->opersize; insn->def_opersize_64 = d->def_opersize_64; insn->special_prefix = d->special_prefix; insn->lockrep_pre = 0; insn->rex = d->rex; insn->shift_op = d->shift_op; insn->signext_imm8_op = d->signext_imm8_op; insn->shortmov_op = d->shortmov_op; insn->mode_bits = arch_x86->mode_bits; return (yasm_bytecode *)insn;}/*@=compmempass =mustfree@*//*@-compmempass -mustfree@*/yasm_bytecode *yasm_x86__bc_create_jmp(yasm_arch *arch, x86_new_jmp_data *d){ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; x86_jmp *jmp; jmp = (x86_jmp *) yasm_bc_create_common(&x86_bc_callback_jmp, sizeof(x86_jmp), d->line); jmp->target = d->target; jmp->origin = d->origin; jmp->op_sel = d->op_sel; if ((d->op_sel == JMP_SHORT_FORCED) && (d->near_op_len == 0)) yasm__error(d->line, N_("no SHORT form of that jump instruction exists")); if ((d->op_sel == JMP_NEAR_FORCED) && (d->short_op_len == 0)) yasm__error(d->line, N_("no NEAR form of that jump instruction exists")); jmp->shortop.opcode[0] = d->short_op[0]; jmp->shortop.opcode[1] = d->short_op[1]; jmp->shortop.opcode[2] = d->short_op[2]; jmp->shortop.opcode_len = d->short_op_len; jmp->nearop.opcode[0] = d->near_op[0]; jmp->nearop.opcode[1] = d->near_op[1]; jmp->nearop.opcode[2] = d->near_op[2]; jmp->nearop.opcode_len = d->near_op_len; jmp->farop.opcode[0] = d->far_op[0]; jmp->farop.opcode[1] = d->far_op[1]; jmp->farop.opcode[2] = d->far_op[2]; jmp->farop.opcode_len = d->far_op_len; jmp->addrsize = d->addrsize; jmp->opersize = d->opersize; jmp->lockrep_pre = 0; jmp->mode_bits = arch_x86->mode_bits; return (yasm_bytecode *)jmp;}/*@=compmempass =mustfree@*/voidyasm_x86__ea_set_segment(yasm_effaddr *ea, unsigned int segment, unsigned long line){ x86_effaddr *x86_ea = (x86_effaddr *)ea; if (!ea) return; if (segment != 0 && x86_ea->segment != 0) yasm__warning(YASM_WARN_GENERAL, line, N_("multiple segment overrides, using leftmost")); x86_ea->segment = (unsigned char)segment;}voidyasm_x86__ea_set_disponly(yasm_effaddr *ea){ x86_effaddr *x86_ea = (x86_effaddr *)ea; x86_ea->valid_modrm = 0; x86_ea->need_modrm = 0; x86_ea->valid_sib = 0; x86_ea->need_sib = 0; x86_ea->pcrel = 0;}yasm_effaddr *yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex, unsigned int bits){ x86_effaddr *x86_ea; unsigned char rm; if (yasm_x86__set_rex_from_reg(rex, &rm, reg, bits, X86_REX_B)) return NULL; x86_ea = yasm_xmalloc(sizeof(x86_effaddr)); x86_ea->ea.callback = &x86_ea_callback; x86_ea->ea.disp = (yasm_expr *)NULL; x86_ea->ea.len = 0; x86_ea->ea.nosplit = 0; x86_ea->segment = 0; x86_ea->modrm = 0xC0 | rm; /* Mod=11, R/M=Reg, Reg=0 */ x86_ea->valid_modrm = 1; x86_ea->need_modrm = 1; x86_ea->sib = 0; x86_ea->valid_sib = 0; x86_ea->need_sib = 0; x86_ea->pcrel = 0; return (yasm_effaddr *)x86_ea;}yasm_effaddr *yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e){ x86_effaddr *x86_ea; x86_ea = yasm_xmalloc(sizeof(x86_effaddr)); x86_ea->ea.callback = &x86_ea_callback; x86_ea->ea.disp = e; x86_ea->ea.len = 0; x86_ea->ea.nosplit = 0; x86_ea->segment = 0; x86_ea->modrm = 0; x86_ea->valid_modrm = 0; x86_ea->need_modrm = 1; x86_ea->sib = 0; x86_ea->valid_sib = 0; /* We won't know whether we need an SIB until we know more about expr and * the BITS/address override setting. */ x86_ea->need_sib = 0xff; x86_ea->pcrel = 0; return (yasm_effaddr *)x86_ea;}/*@-compmempass@*/yasm_effaddr *yasm_x86__ea_create_imm(yasm_expr *imm, unsigned int im_len){ x86_effaddr *x86_ea; x86_ea = yasm_xmalloc(sizeof(x86_effaddr)); x86_ea->ea.callback = &x86_ea_callback; x86_ea->ea.disp = imm; x86_ea->ea.len = (unsigned char)im_len; x86_ea->ea.nosplit = 0; x86_ea->segment = 0; x86_ea->modrm = 0; x86_ea->valid_modrm = 0; x86_ea->need_modrm = 0; x86_ea->sib = 0; x86_ea->valid_sib = 0; x86_ea->need_sib = 0; x86_ea->pcrel = 0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -