Home | History | Annotate | Download | only in libyasm
      1 /*
      2  * ORG bytecode
      3  *
      4  *  Copyright (C) 2005-2007  Peter Johnson
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     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
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
     19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     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
     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
     25  * POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 #include "util.h"
     28 
     29 #include "libyasm-stdint.h"
     30 #include "coretype.h"
     31 #include "file.h"
     32 
     33 #include "errwarn.h"
     34 #include "intnum.h"
     35 #include "expr.h"
     36 #include "value.h"
     37 
     38 #include "bytecode.h"
     39 
     40 
     41 typedef struct bytecode_org {
     42     unsigned long start;        /* target starting offset within section */
     43     unsigned long fill;         /* fill value */
     44 } bytecode_org;
     45 
     46 static void bc_org_destroy(void *contents);
     47 static void bc_org_print(const void *contents, FILE *f, int indent_level);
     48 static void bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
     49 static int bc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
     50                            void *add_span_data);
     51 static int bc_org_expand(yasm_bytecode *bc, int span, long old_val,
     52                          long new_val, /*@out@*/ long *neg_thres,
     53                          /*@out@*/ long *pos_thres);
     54 static int bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp,
     55                           unsigned char *bufstart, void *d,
     56                           yasm_output_value_func output_value,
     57                           /*@null@*/ yasm_output_reloc_func output_reloc);
     58 
     59 static const yasm_bytecode_callback bc_org_callback = {
     60     bc_org_destroy,
     61     bc_org_print,
     62     bc_org_finalize,
     63     NULL,
     64     bc_org_calc_len,
     65     bc_org_expand,
     66     bc_org_tobytes,
     67     YASM_BC_SPECIAL_OFFSET
     68 };
     69 
     70 
     71 static void
     72 bc_org_destroy(void *contents)
     73 {
     74     yasm_xfree(contents);
     75 }
     76 
     77 static void
     78 bc_org_print(const void *contents, FILE *f, int indent_level)
     79 {
     80     const bytecode_org *org = (const bytecode_org *)contents;
     81     fprintf(f, "%*s_Org_\n", indent_level, "");
     82     fprintf(f, "%*sStart=%lu\n", indent_level, "", org->start);
     83 }
     84 
     85 static void
     86 bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
     87 {
     88 }
     89 
     90 static int
     91 bc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
     92                 void *add_span_data)
     93 {
     94     bytecode_org *org = (bytecode_org *)bc->contents;
     95     long neg_thres = 0;
     96     long pos_thres = org->start;
     97 
     98     if (bc_org_expand(bc, 0, 0, (long)bc->offset, &neg_thres, &pos_thres) < 0)
     99         return -1;
    100 
    101     return 0;
    102 }
    103 
    104 static int
    105 bc_org_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
    106               /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
    107 {
    108     bytecode_org *org = (bytecode_org *)bc->contents;
    109 
    110     /* Check for overrun */
    111     if ((unsigned long)new_val > org->start) {
    112         yasm_error_set(YASM_ERROR_GENERAL,
    113                        N_("ORG overlap with already existing data"));
    114         return -1;
    115     }
    116 
    117     /* Generate space to start offset */
    118     bc->len = org->start - new_val;
    119     return 1;
    120 }
    121 
    122 static int
    123 bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp,
    124                unsigned char *bufstart, void *d,
    125                yasm_output_value_func output_value,
    126                /*@unused@*/ yasm_output_reloc_func output_reloc)
    127 {
    128     bytecode_org *org = (bytecode_org *)bc->contents;
    129     unsigned long len, i;
    130 
    131     /* Sanity check for overrun */
    132     if (bc->offset > org->start) {
    133         yasm_error_set(YASM_ERROR_GENERAL,
    134                        N_("ORG overlap with already existing data"));
    135         return 1;
    136     }
    137     len = org->start - bc->offset;
    138     for (i=0; i<len; i++)
    139         YASM_WRITE_8(*bufp, org->fill);     /* XXX: handle more than 8 bit? */
    140     return 0;
    141 }
    142 
    143 yasm_bytecode *
    144 yasm_bc_create_org(unsigned long start, unsigned long fill, unsigned long line)
    145 {
    146     bytecode_org *org = yasm_xmalloc(sizeof(bytecode_org));
    147 
    148     org->start = start;
    149     org->fill = fill;
    150 
    151     return yasm_bc_create_common(&bc_org_callback, org, line);
    152 }
    153