| /** |
| * \file libyasm/bytecode.h |
| * \brief YASM bytecode interface. |
| * |
| * \rcs |
| * $Id$ |
| * \endrcs |
| * |
| * \license |
| * 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: |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * - 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. |
| * \endlicense |
| */ |
| #ifndef YASM_BYTECODE_H |
| #define YASM_BYTECODE_H |
| |
| /** An effective address. */ |
| typedef struct yasm_effaddr yasm_effaddr; |
| |
| /** Callbacks for effective address implementations. */ |
| typedef struct yasm_effaddr_callback { |
| /** Destroy the effective address (freeing it). |
| * \param ea effective address |
| */ |
| void (*destroy) (/*@only@*/ yasm_effaddr *ea); |
| |
| /** Print the effective address. |
| * \param ea effective address |
| * \param f file to output to |
| * \param indent_level indentation level |
| */ |
| void (*print) (const yasm_effaddr *ea, FILE *f, int indent_level); |
| } yasm_effaddr_callback; |
| |
| /** An effective address. */ |
| struct yasm_effaddr { |
| const yasm_effaddr_callback *callback; /**< callback functions */ |
| |
| yasm_value disp; /**< address displacement */ |
| |
| unsigned long segreg; /**< segment register override (0 if none) */ |
| |
| unsigned char disp_len; /**< length of disp (in bytes), 0 if unknown, |
| * 0xff if unknown and required to be >0. |
| */ |
| unsigned char need_disp; /**< 1 if a displacement should be present |
| * in the output. |
| */ |
| unsigned char nosplit; /**< 1 if reg*2 should not be split into |
| * reg+reg. (0 if not) |
| */ |
| unsigned char strong; /**< 1 if effective address is *definitely* |
| * an effective address, e.g. in GAS if |
| * expr(,1) form is used vs. just expr. |
| */ |
| }; |
| |
| /** An immediate value. */ |
| typedef struct yasm_immval { |
| yasm_value val; /**< the immediate value itself */ |
| |
| unsigned char len; /**< final length (in bytes), 0 if unknown */ |
| unsigned char sign; /**< 1 if final imm is treated as signed */ |
| } yasm_immval; |
| |
| /** A data value (opaque type). */ |
| typedef struct yasm_dataval yasm_dataval; |
| /** A list of data values (opaque type). */ |
| typedef struct yasm_datavalhead yasm_datavalhead; |
| |
| #ifdef YASM_LIB_INTERNAL |
| /*@reldef@*/ STAILQ_HEAD(yasm_datavalhead, yasm_dataval); |
| #endif |
| |
| /** Return value flags for yasm_bc_resolve(). */ |
| typedef enum { |
| YASM_BC_RESOLVE_NONE = 0, /**< Ok, but length is not minimum. */ |
| YASM_BC_RESOLVE_ERROR = 1<<0, /**< Error found, output. */ |
| YASM_BC_RESOLVE_MIN_LEN = 1<<1, /**< Length is minimum possible. */ |
| YASM_BC_RESOLVE_UNKNOWN_LEN = 1<<2 /**< Length indeterminate. */ |
| } yasm_bc_resolve_flags; |
| |
| /** Create an immediate value from an expression. |
| * \param e expression (kept, do not free). |
| * \return Newly allocated immediate value. |
| */ |
| /*@only@*/ yasm_immval *yasm_imm_create_expr(/*@keep@*/ yasm_expr *e); |
| |
| /** Get the displacement portion of an effective address. |
| * \param ea effective address |
| * \return Expression representing the displacement (read-only). |
| */ |
| /*@observer@*/ const yasm_expr *yasm_ea_get_disp(const yasm_effaddr *ea); |
| |
| /** Set the length of the displacement portion of an effective address. |
| * The length is specified in bytes. |
| * \param ea effective address |
| * \param len length in bytes |
| */ |
| void yasm_ea_set_len(yasm_effaddr *ea, unsigned int len); |
| |
| /** Set/clear nosplit flag of an effective address. |
| * The nosplit flag indicates (for architectures that support complex effective |
| * addresses such as x86) if various types of complex effective addresses can |
| * be split into different forms in order to minimize instruction length. |
| * \param ea effective address |
| * \param nosplit nosplit flag setting (0=splits allowed, nonzero=splits |
| * not allowed) |
| */ |
| void yasm_ea_set_nosplit(yasm_effaddr *ea, unsigned int nosplit); |
| |
| /** Set/clear strong flag of an effective address. |
| * The strong flag indicates if an effective address is *definitely* an |
| * effective address. This is used in e.g. the GAS parser to differentiate |
| * between "expr" (which might or might not be an effective address) and |
| * "expr(,1)" (which is definitely an effective address). |
| * \param ea effective address |
| * \param strong strong flag setting (0=not strong, nonzero=strong) |
| */ |
| void yasm_ea_set_strong(yasm_effaddr *ea, unsigned int strong); |
| |
| /** Set segment override for an effective address. |
| * Some architectures (such as x86) support segment overrides on effective |
| * addresses. A override of an override will result in a warning. |
| * \param ea effective address |
| * \param segreg segment register (0 if none) |
| * \param line virtual line number |
| */ |
| void yasm_ea_set_segreg(yasm_effaddr *ea, unsigned long segreg, |
| unsigned long line); |
| |
| /** Delete (free allocated memory for) an effective address. |
| * \param ea effective address (only pointer to it). |
| */ |
| void yasm_ea_destroy(/*@only@*/ yasm_effaddr *ea); |
| |
| /** Print an effective address. For debugging purposes. |
| * \param f file |
| * \param indent_level indentation level |
| * \param ea effective address |
| */ |
| void yasm_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level); |
| |
| /** Set multiple field of a bytecode. |
| * A bytecode can be repeated a number of times when output. This function |
| * sets that multiple. |
| * \param bc bytecode |
| * \param e multiple (kept, do not free) |
| */ |
| void yasm_bc_set_multiple(yasm_bytecode *bc, /*@keep@*/ yasm_expr *e); |
| |
| /** Create a bytecode containing data value(s). |
| * \param datahead list of data values (kept, do not free) |
| * \param size storage size (in bytes) for each data value |
| * \param append_zero append a single zero byte after each data value |
| * (if non-zero) |
| * \param line virtual line (from yasm_linemap) |
| * \return Newly allocated bytecode. |
| */ |
| /*@only@*/ yasm_bytecode *yasm_bc_create_data |
| (yasm_datavalhead *datahead, unsigned int size, int append_zero, |
| unsigned long line); |
| |
| /** Create a bytecode containing LEB128-encoded data value(s). |
| * \param datahead list of data values (kept, do not free) |
| * \param sign signedness (1=signed, 0=unsigned) of each data value |
| * \param line virtual line (from yasm_linemap) |
| * \return Newly allocated bytecode. |
| */ |
| /*@only@*/ yasm_bytecode *yasm_bc_create_leb128 |
| (yasm_datavalhead *datahead, int sign, unsigned long line); |
| |
| /** Create a bytecode reserving space. |
| * \param numitems number of reserve "items" (kept, do not free) |
| * \param itemsize reserved size (in bytes) for each item |
| * \param line virtual line (from yasm_linemap) |
| * \return Newly allocated bytecode. |
| */ |
| /*@only@*/ yasm_bytecode *yasm_bc_create_reserve |
| (/*@only@*/ yasm_expr *numitems, unsigned int itemsize, |
| unsigned long line); |
| |
| /** Create a bytecode that includes a binary file verbatim. |
| * \param filename full path to binary file (kept, do not free) |
| * \param start starting location in file (in bytes) to read data from |
| * (kept, do not free); may be NULL to indicate 0 |
| * \param maxlen maximum number of bytes to read from the file (kept, do |
| * do not free); may be NULL to indicate no maximum |
| * \param line virtual line (from yasm_linemap) for the bytecode |
| * \return Newly allocated bytecode. |
| */ |
| /*@only@*/ yasm_bytecode *yasm_bc_create_incbin |
| (/*@only@*/ char *filename, /*@only@*/ /*@null@*/ yasm_expr *start, |
| /*@only@*/ /*@null@*/ yasm_expr *maxlen, unsigned long line); |
| |
| /** Create a bytecode that aligns the following bytecode to a boundary. |
| * \param boundary byte alignment (must be a power of two) |
| * \param fill fill data (if NULL, code_fill or 0 is used) |
| * \param maxskip maximum number of bytes to skip |
| * \param code_fill code fill data (if NULL, 0 is used) |
| * \param line virtual line (from yasm_linemap) |
| * \return Newly allocated bytecode. |
| * \note The precedence on generated fill is as follows: |
| * - from fill parameter (if not NULL) |
| * - from code_fill parameter (if not NULL) |
| * - 0 |
| */ |
| /*@only@*/ yasm_bytecode *yasm_bc_create_align |
| (/*@keep@*/ yasm_expr *boundary, /*@keep@*/ /*@null@*/ yasm_expr *fill, |
| /*@keep@*/ /*@null@*/ yasm_expr *maxskip, |
| /*@null@*/ const unsigned char **code_fill, unsigned long line); |
| |
| /** Create a bytecode that puts the following bytecode at a fixed section |
| * offset. |
| * \param start section offset of following bytecode |
| * \param line virtual line (from yasm_linemap) |
| * \return Newly allocated bytecode. |
| */ |
| /*@only@*/ yasm_bytecode *yasm_bc_create_org |
| (unsigned long start, unsigned long line); |
| |
| /** Create a bytecode that represents a single instruction. |
| * \param arch instruction's architecture |
| * \param insn_data data that identifies the type of instruction |
| * \param num_operands number of operands |
| * \param operands instruction operands (may be NULL if no operands) |
| * \param line virtual line (from yasm_linemap) |
| * \return Newly allocated bytecode. |
| * \note Keeps the list of operands; do not call yasm_ops_delete() after |
| * giving operands to this function. |
| */ |
| /*@only@*/ yasm_bytecode *yasm_bc_create_insn |
| (yasm_arch *arch, const unsigned long insn_data[4], int num_operands, |
| /*@null@*/ yasm_insn_operands *operands, unsigned long line); |
| |
| /** Create a bytecode that represents a single empty (0 length) instruction. |
| * This is used for handling solitary prefixes. |
| * \param arch instruction's architecture |
| * \param line virtual line (from yasm_linemap) |
| * \return Newly allocated bytecode. |
| */ |
| /*@only@*/ yasm_bytecode *yasm_bc_create_empty_insn(yasm_arch *arch, |
| unsigned long line); |
| |
| /** Associate a prefix with an instruction bytecode. |
| * \param bc instruction bytecode |
| * \param prefix_data data the identifies the prefix |
| */ |
| void yasm_bc_insn_add_prefix(yasm_bytecode *bc, |
| const unsigned long prefix_data[4]); |
| |
| /** Associate a segment prefix with an instruction bytecode. |
| * \param bc instruction bytecode |
| * \param segreg data the identifies the segment register |
| */ |
| void yasm_bc_insn_add_seg_prefix(yasm_bytecode *bc, unsigned long segreg); |
| |
| /** Get the section that contains a particular bytecode. |
| * \param bc bytecode |
| * \return Section containing bc (can be NULL if bytecode is not part of a |
| * section). |
| */ |
| /*@dependent@*/ /*@null@*/ yasm_section *yasm_bc_get_section |
| (yasm_bytecode *bc); |
| |
| #ifdef YASM_LIB_INTERNAL |
| /** Add to the list of symrecs that reference a bytecode. For symrec use |
| * only. |
| * \param bc bytecode |
| * \param sym symbol |
| */ |
| void yasm_bc__add_symrec(yasm_bytecode *bc, /*@dependent@*/ yasm_symrec *sym); |
| #endif |
| |
| /** Delete (free allocated memory for) a bytecode. |
| * \param bc bytecode (only pointer to it); may be NULL |
| */ |
| void yasm_bc_destroy(/*@only@*/ /*@null@*/ yasm_bytecode *bc); |
| |
| /** Print a bytecode. For debugging purposes. |
| * \param f file |
| * \param indent_level indentation level |
| * \param bc bytecode |
| */ |
| void yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level); |
| |
| /** Finalize a bytecode after parsing. |
| * \param bc bytecode |
| * \param prev_bc bytecode directly preceding bc in a list of bytecodes |
| */ |
| void yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); |
| |
| /** Common version of calc_bc_dist that takes offsets from bytecodes. |
| * Should be used for the final stages of optimizers as well as in yasm_objfmt |
| * yasm_expr output functions. |
| * \see yasm_calc_bc_dist_func for parameter descriptions. |
| */ |
| /*@null@*/ /*@only@*/ yasm_intnum *yasm_common_calc_bc_dist |
| (yasm_bytecode *precbc1, yasm_bytecode *precbc2); |
| |
| /** Resolve labels in a bytecode, and calculate its length. |
| * Tries to minimize the length as much as possible. |
| * \note Sometimes it's impossible to determine if a length is the minimum |
| * possible. In this case, this function returns that the length is NOT |
| * the minimum. |
| * \param bc bytecode |
| * \param save when zero, this function does \em not modify bc other |
| * than the length/size values (i.e. it doesn't keep the |
| * values returned by calc_bc_dist except temporarily to |
| * try to minimize the length); when nonzero, all fields |
| * in bc may be modified by this function |
| * \param calc_bc_dist function used to determine bytecode distance |
| * \return Flags indicating whether the length is the minimum possible, |
| * indeterminate, and if there was an error recognized (and output) |
| * during execution. |
| */ |
| yasm_bc_resolve_flags yasm_bc_resolve(yasm_bytecode *bc, int save, |
| yasm_calc_bc_dist_func calc_bc_dist); |
| |
| /** Convert a bytecode into its byte representation. |
| * \param bc bytecode |
| * \param buf byte representation destination buffer |
| * \param bufsize size of buf (in bytes) prior to call; size of the |
| * generated data after call |
| * \param multiple number of times the data should be duplicated when |
| * written to the object file [output] |
| * \param gap if nonzero, indicates the data does not really need to |
| * exist in the object file; if nonzero, contents of buf |
| * are undefined [output] |
| * \param d data to pass to each call to output_value/output_reloc |
| * \param output_value function to call to convert values into their byte |
| * representation |
| * \param output_reloc function to call to output relocation entries |
| * for a single sym |
| * \return Newly allocated buffer that should be used instead of buf for |
| * reading the byte representation, or NULL if buf was big enough to |
| * hold the entire byte representation. |
| * \note Calling twice on the same bytecode may \em not produce the same |
| * results on the second call, as calling this function may result in |
| * non-reversible changes to the bytecode. |
| */ |
| /*@null@*/ /*@only@*/ unsigned char *yasm_bc_tobytes |
| (yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize, |
| /*@out@*/ unsigned long *multiple, /*@out@*/ int *gap, void *d, |
| yasm_output_value_func output_value, |
| /*@null@*/ yasm_output_reloc_func output_reloc) |
| /*@sets *buf@*/; |
| |
| /** Create a new data value from an expression. |
| * \param expn expression |
| * \return Newly allocated data value. |
| */ |
| yasm_dataval *yasm_dv_create_expr(/*@keep@*/ yasm_expr *expn); |
| |
| /** Create a new data value from a string. |
| * \param contents string (raw, may contain NULs) |
| * \param len length of string |
| * \return Newly allocated data value. |
| */ |
| yasm_dataval *yasm_dv_create_string(/*@keep@*/ char *contents, size_t len); |
| |
| /** Initialize a list of data values. |
| * \param headp list of data values |
| */ |
| void yasm_dvs_initialize(yasm_datavalhead *headp); |
| #ifdef YASM_LIB_INTERNAL |
| #define yasm_dvs_initialize(headp) STAILQ_INIT(headp) |
| #endif |
| |
| /** Delete (free allocated memory for) a list of data values. |
| * \param headp list of data values |
| */ |
| void yasm_dvs_destroy(yasm_datavalhead *headp); |
| |
| /** Add data value to the end of a list of data values. |
| * \note Does not make a copy of the data value; so don't pass this function |
| * static or local variables, and discard the dv pointer after calling |
| * this function. |
| * \param headp data value list |
| * \param dv data value (may be NULL) |
| * \return If data value was actually appended (it wasn't NULL), the data |
| * value; otherwise NULL. |
| */ |
| /*@null@*/ yasm_dataval *yasm_dvs_append |
| (yasm_datavalhead *headp, /*@returned@*/ /*@null@*/ yasm_dataval *dv); |
| |
| /** Print a data value list. For debugging purposes. |
| * \param f file |
| * \param indent_level indentation level |
| * \param headp data value list |
| */ |
| void yasm_dvs_print(const yasm_datavalhead *headp, FILE *f, int indent_level); |
| |
| #endif |