Home | History | Annotate | Download | only in libyasm
      1 /*
      2  * Data (and LEB128) bytecode
      3  *
      4  *  Copyright (C) 2001-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 
     32 #include "errwarn.h"
     33 #include "intnum.h"
     34 #include "expr.h"
     35 #include "value.h"
     36 
     37 #include "bytecode.h"
     38 #include "arch.h"
     39 
     40 
     41 struct yasm_dataval {
     42     /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link;
     43 
     44     enum { DV_EMPTY, DV_VALUE, DV_RAW, DV_ULEB128, DV_SLEB128, DV_RESERVE }
     45         type;
     46 
     47     union {
     48         yasm_value val;
     49         struct {
     50             /*@only@*/ unsigned char *contents;
     51             unsigned long len;
     52         } raw;
     53     } data;
     54 
     55     /* number of times data is repeated, NULL=1. */
     56     /*@only@*/ /*@null@*/ yasm_expr *multiple;
     57 };
     58 
     59 typedef struct bytecode_data {
     60     /* converted data (linked list) */
     61     yasm_datavalhead datahead;
     62 
     63     int item_size;
     64 } bytecode_data;
     65 
     66 static void bc_data_destroy(void *contents);
     67 static void bc_data_print(const void *contents, FILE *f, int indent_level);
     68 static void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
     69 static int bc_data_item_size(yasm_bytecode *bc);
     70 static int bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
     71                             void *add_span_data);
     72 static int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp,
     73                            unsigned char *bufstart, void *d,
     74                            yasm_output_value_func output_value,
     75                            /*@null@*/ yasm_output_reloc_func output_reloc);
     76 
     77 static const yasm_bytecode_callback bc_data_callback = {
     78     bc_data_destroy,
     79     bc_data_print,
     80     bc_data_finalize,
     81     bc_data_item_size,
     82     bc_data_calc_len,
     83     yasm_bc_expand_common,
     84     bc_data_tobytes,
     85     0
     86 };
     87 
     88 
     89 static void
     90 bc_data_destroy(void *contents)
     91 {
     92     bytecode_data *bc_data = (bytecode_data *)contents;
     93     yasm_dvs_delete(&bc_data->datahead);
     94     yasm_xfree(contents);
     95 }
     96 
     97 static void
     98 bc_data_print(const void *contents, FILE *f, int indent_level)
     99 {
    100     const bytecode_data *bc_data = (const bytecode_data *)contents;
    101     fprintf(f, "%*s_Data_\n", indent_level, "");
    102     fprintf(f, "%*sElements:\n", indent_level+1, "");
    103     yasm_dvs_print(&bc_data->datahead, f, indent_level+2);
    104 }
    105 
    106 static void
    107 bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
    108 {
    109     bytecode_data *bc_data = (bytecode_data *)bc->contents;
    110     yasm_dataval *dv;
    111     yasm_intnum *intn;
    112 
    113     /* Convert values from simple expr to value. */
    114     STAILQ_FOREACH(dv, &bc_data->datahead, link) {
    115         switch (dv->type) {
    116             case DV_VALUE:
    117                 if (yasm_value_finalize(&dv->data.val, prev_bc)) {
    118                     yasm_error_set(YASM_ERROR_TOO_COMPLEX,
    119                                    N_("data expression too complex"));
    120                     return;
    121                 }
    122                 break;
    123             case DV_ULEB128:
    124             case DV_SLEB128:
    125                 intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
    126                 if (!intn) {
    127                     yasm_error_set(YASM_ERROR_NOT_CONSTANT,
    128                                    N_("LEB128 requires constant values"));
    129                     return;
    130                 }
    131                 /* Warn for negative values in unsigned environment.
    132                  * This could be an error instead: the likelihood this is
    133                  * desired is very low!
    134                  */
    135                 if (yasm_intnum_sign(intn) == -1 && dv->type == DV_ULEB128)
    136                     yasm_warn_set(YASM_WARN_GENERAL,
    137                                   N_("negative value in unsigned LEB128"));
    138                 break;
    139             default:
    140                 break;
    141         }
    142         if (dv->multiple) {
    143             yasm_value val;
    144             if (yasm_value_finalize_expr(&val, dv->multiple, prev_bc, 0))
    145                 yasm_error_set(YASM_ERROR_TOO_COMPLEX,
    146                                N_("multiple expression too complex"));
    147             else if (val.rel)
    148                 yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
    149                                N_("multiple expression not absolute"));
    150             dv->multiple = val.abs;
    151         }
    152     }
    153 }
    154 
    155 static int
    156 bc_data_item_size(yasm_bytecode *bc)
    157 {
    158     bytecode_data *bc_data = (bytecode_data *)bc->contents;
    159     return bc_data->item_size;
    160 }
    161 
    162 static int
    163 bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
    164                  void *add_span_data)
    165 {
    166     bytecode_data *bc_data = (bytecode_data *)bc->contents;
    167     yasm_dataval *dv;
    168     yasm_intnum *intn;
    169     unsigned long len = 0;
    170     unsigned long multiple;
    171 
    172     /* Count up element sizes, rounding up string length. */
    173     STAILQ_FOREACH(dv, &bc_data->datahead, link) {
    174         switch (dv->type) {
    175             case DV_EMPTY:
    176                 len = 0;
    177                 break;
    178             case DV_VALUE:
    179                 len = dv->data.val.size/8;
    180                 break;
    181             case DV_RAW:
    182                 len = dv->data.raw.len;
    183                 break;
    184             case DV_ULEB128:
    185             case DV_SLEB128:
    186                 intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
    187                 if (!intn)
    188                     yasm_internal_error(N_("non-constant in data_tobytes"));
    189                 len = yasm_intnum_size_leb128(intn, dv->type == DV_SLEB128);
    190                 break;
    191             case DV_RESERVE:
    192                 len = dv->data.val.size/8;
    193                 break;
    194         }
    195 
    196         if (!yasm_dv_get_multiple(dv, &multiple))
    197             len *= multiple;
    198 
    199         bc->len += len;
    200     }
    201 
    202     return 0;
    203 }
    204 
    205 static int
    206 bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp,
    207                 unsigned char *bufstart, void *d,
    208                 yasm_output_value_func output_value,
    209                 /*@unused@*/ yasm_output_reloc_func output_reloc)
    210 {
    211     bytecode_data *bc_data = (bytecode_data *)bc->contents;
    212     yasm_dataval *dv;
    213     yasm_intnum *intn;
    214     unsigned int val_len;
    215     unsigned long multiple, i;
    216 
    217     STAILQ_FOREACH(dv, &bc_data->datahead, link) {
    218         if (yasm_dv_get_multiple(dv, &multiple) || multiple == 0)
    219             continue;
    220         switch (dv->type) {
    221             case DV_EMPTY:
    222                 break;
    223             case DV_VALUE:
    224                 val_len = dv->data.val.size/8;
    225                 for (i=0; i<multiple; i++) {
    226                     if (output_value(&dv->data.val, *bufp, val_len,
    227                                      (unsigned long)(*bufp-bufstart), bc, 1,
    228                                      d))
    229                         return 1;
    230                     *bufp += val_len;
    231                 }
    232                 break;
    233             case DV_RAW:
    234                 for (i=0; i<multiple; i++) {
    235                     memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len);
    236                     *bufp += dv->data.raw.len;
    237                 }
    238                 break;
    239             case DV_ULEB128:
    240             case DV_SLEB128:
    241                 intn = yasm_expr_get_intnum(&dv->data.val.abs, 234);
    242                 if (!intn)
    243                     yasm_internal_error(N_("non-constant in data_tobytes"));
    244                 for (i=0; i<multiple; i++) {
    245                     *bufp +=
    246                         yasm_intnum_get_leb128(intn, *bufp,
    247                                 dv->type == DV_SLEB128);
    248                 }
    249             case DV_RESERVE:
    250                 val_len = dv->data.val.size/8;
    251                 for (i=0; i<multiple; i++) {
    252                     memset(*bufp, 0, val_len);
    253                     *bufp += val_len;
    254                 }
    255                 break;
    256         }
    257     }
    258 
    259     return 0;
    260 }
    261 
    262 yasm_bytecode *
    263 yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
    264                     int append_zero, yasm_arch *arch, unsigned long line)
    265 {
    266     bytecode_data *data = yasm_xmalloc(sizeof(bytecode_data));
    267     yasm_bytecode *bc = yasm_bc_create_common(&bc_data_callback, data, line);
    268     yasm_dataval *dv, *dv2, *dvo;
    269     yasm_intnum *intn;
    270     unsigned long len = 0, rlen, i;
    271 
    272 
    273     yasm_dvs_initialize(&data->datahead);
    274     data->item_size = size;
    275 
    276     /* Prescan input data for length, etc.  Careful: this needs to be
    277      * precisely paired with the second loop.
    278      */
    279     STAILQ_FOREACH(dv, datahead, link) {
    280         if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
    281             /* Flush previous data */
    282             dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
    283             STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
    284             len = 0;
    285         }
    286         switch (dv->type) {
    287             case DV_EMPTY:
    288                 break;
    289             case DV_VALUE:
    290             case DV_ULEB128:
    291             case DV_SLEB128:
    292                 intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
    293                 if (intn && dv->type == DV_VALUE && (arch || size == 1))
    294                     len += size;
    295                 else if (intn && dv->type == DV_ULEB128)
    296                     len += yasm_intnum_size_leb128(intn, 0);
    297                 else if (intn && dv->type == DV_SLEB128)
    298                     len += yasm_intnum_size_leb128(intn, 1);
    299                 else {
    300                     if (len > 0) {
    301                         /* Create bytecode for all previous len */
    302                         dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
    303                         STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
    304                         len = 0;
    305                     }
    306 
    307                     /* Create bytecode for this value */
    308                     dvo = yasm_xmalloc(sizeof(yasm_dataval));
    309                     STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
    310                     dvo->multiple = dv->multiple;
    311                 }
    312                 break;
    313             case DV_RAW:
    314                 rlen = dv->data.raw.len;
    315                 /* find count, rounding up to nearest multiple of size */
    316                 rlen = (rlen + size - 1) / size;
    317                 len += rlen*size;
    318                 break;
    319             case DV_RESERVE:
    320                 len += size;
    321                 break;
    322         }
    323 
    324         if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
    325             /* Flush this data */
    326             dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
    327             STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
    328             dvo->multiple = dv->multiple;
    329             len = 0;
    330         }
    331 
    332         if (append_zero)
    333             len++;
    334     }
    335 
    336     /* Create final dataval for any trailing length */
    337     if (len > 0) {
    338         dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
    339         STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
    340     }
    341 
    342     /* Second iteration: copy data and delete input datavals. */
    343     dv = STAILQ_FIRST(datahead);
    344     dvo = STAILQ_FIRST(&data->datahead);
    345     len = 0;
    346     while (dv && dvo) {
    347         if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
    348             dvo = STAILQ_NEXT(dvo, link);
    349             len = 0;
    350         }
    351         switch (dv->type) {
    352             case DV_EMPTY:
    353                 break;
    354             case DV_VALUE:
    355             case DV_ULEB128:
    356             case DV_SLEB128:
    357                 intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
    358                 if (intn && dv->type == DV_VALUE && (arch || size == 1)) {
    359                     if (size == 1)
    360                         yasm_intnum_get_sized(intn,
    361                                               &dvo->data.raw.contents[len],
    362                                               1, 8, 0, 0, 1);
    363                     else
    364                         yasm_arch_intnum_tobytes(arch, intn,
    365                                                  &dvo->data.raw.contents[len],
    366                                                  size, size*8, 0, bc, 1);
    367                     yasm_value_delete(&dv->data.val);
    368                     len += size;
    369                 } else if (intn && dv->type == DV_ULEB128) {
    370                     len += yasm_intnum_get_leb128(intn,
    371                                                   &dvo->data.raw.contents[len],
    372                                                   0);
    373                     yasm_value_delete(&dv->data.val);
    374                 } else if (intn && dv->type == DV_SLEB128) {
    375                     len += yasm_intnum_get_leb128(intn,
    376                                                   &dvo->data.raw.contents[len],
    377                                                   1);
    378                     yasm_value_delete(&dv->data.val);
    379                 } else {
    380                     if (len > 0)
    381                         dvo = STAILQ_NEXT(dvo, link);
    382                     dvo->type = dv->type;
    383                     dvo->data.val = dv->data.val;   /* structure copy */
    384                     dvo->data.val.size = size*8;    /* remember size */
    385                     dvo = STAILQ_NEXT(dvo, link);
    386                     len = 0;
    387                 }
    388                 break;
    389             case DV_RAW:
    390                 rlen = dv->data.raw.len;
    391                 memcpy(&dvo->data.raw.contents[len], dv->data.raw.contents,
    392                        rlen);
    393                 yasm_xfree(dv->data.raw.contents);
    394                 len += rlen;
    395                 /* pad with 0's to nearest multiple of size */
    396                 rlen %= size;
    397                 if (rlen > 0) {
    398                     rlen = size-rlen;
    399                     for (i=0; i<rlen; i++)
    400                         dvo->data.raw.contents[len++] = 0;
    401                 }
    402                 break;
    403             case DV_RESERVE:
    404                 memset(&dvo->data.raw.contents[len], 0, size);
    405                 len += size;
    406                 break;
    407         }
    408 
    409         if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
    410             dvo = STAILQ_NEXT(dvo, link);
    411             len = 0;
    412         }
    413 
    414         if (append_zero)
    415             dvo->data.raw.contents[len++] = 0;
    416         dv2 = STAILQ_NEXT(dv, link);
    417         yasm_xfree(dv);
    418         dv = dv2;
    419     }
    420 
    421     return bc;
    422 }
    423 
    424 yasm_bytecode *
    425 yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
    426 {
    427     yasm_dataval *dv;
    428 
    429     /* Convert all values into LEB type, error on strings/raws */
    430     STAILQ_FOREACH(dv, datahead, link) {
    431         switch (dv->type) {
    432             case DV_VALUE:
    433                 dv->type = sign ? DV_SLEB128 : DV_ULEB128;
    434                 break;
    435             case DV_RAW:
    436                 yasm_error_set(YASM_ERROR_VALUE,
    437                                N_("LEB128 does not allow string constants"));
    438                 break;
    439             default:
    440                 break;
    441         }
    442     }
    443 
    444     return yasm_bc_create_data(datahead, 0, 0, 0, line);
    445 }
    446 
    447 yasm_dataval *
    448 yasm_dv_create_expr(yasm_expr *e)
    449 {
    450     yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
    451 
    452     retval->type = DV_VALUE;
    453     yasm_value_initialize(&retval->data.val, e, 0);
    454     retval->multiple = NULL;
    455 
    456     return retval;
    457 }
    458 
    459 yasm_dataval *
    460 yasm_dv_create_raw(unsigned char *contents, unsigned long len)
    461 {
    462     yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
    463 
    464     retval->type = DV_RAW;
    465     retval->data.raw.contents = contents;
    466     retval->data.raw.len = len;
    467     retval->multiple = NULL;
    468 
    469     return retval;
    470 }
    471 
    472 yasm_dataval *
    473 yasm_dv_create_reserve(void)
    474 {
    475     yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
    476 
    477     retval->type = DV_RESERVE;
    478     retval->multiple = NULL;
    479 
    480     return retval;
    481 }
    482 
    483 yasm_value *
    484 yasm_dv_get_value(yasm_dataval *dv)
    485 {
    486     if (dv->type != DV_VALUE)
    487         return NULL;
    488     return &dv->data.val;
    489 }
    490 
    491 void
    492 yasm_dv_set_multiple(yasm_dataval *dv, yasm_expr *e)
    493 {
    494     if (dv->multiple)
    495         dv->multiple = yasm_expr_create_tree( dv->multiple, YASM_EXPR_MUL, e,
    496                                              e->line);
    497     else
    498         dv->multiple = e;
    499 }
    500 
    501 int
    502 yasm_dv_get_multiple(yasm_dataval *dv, unsigned long *multiple)
    503 {
    504     /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
    505 
    506     *multiple = 1;
    507     if (dv->multiple) {
    508         num = yasm_expr_get_intnum(&dv->multiple, 0);
    509         if (!num) {
    510             yasm_error_set(YASM_ERROR_VALUE,
    511                            N_("could not determine multiple"));
    512             return 1;
    513         }
    514         if (yasm_intnum_sign(num) < 0) {
    515             yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
    516             return 1;
    517         }
    518         *multiple = yasm_intnum_get_uint(num);
    519     }
    520     return 0;
    521 }
    522 
    523 void
    524 yasm_dvs_delete(yasm_datavalhead *headp)
    525 {
    526     yasm_dataval *cur, *next;
    527 
    528     cur = STAILQ_FIRST(headp);
    529     while (cur) {
    530         next = STAILQ_NEXT(cur, link);
    531         switch (cur->type) {
    532             case DV_VALUE:
    533                 yasm_value_delete(&cur->data.val);
    534                 break;
    535             case DV_RAW:
    536                 yasm_xfree(cur->data.raw.contents);
    537                 break;
    538             default:
    539                 break;
    540         }
    541         if (cur->multiple)
    542             yasm_expr_destroy(cur->multiple);
    543         yasm_xfree(cur);
    544         cur = next;
    545     }
    546     STAILQ_INIT(headp);
    547 }
    548 
    549 yasm_dataval *
    550 yasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv)
    551 {
    552     if (dv) {
    553         STAILQ_INSERT_TAIL(headp, dv, link);
    554         return dv;
    555     }
    556     return (yasm_dataval *)NULL;
    557 }
    558 
    559 void
    560 yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
    561 {
    562     yasm_dataval *cur;
    563     unsigned long i;
    564 
    565     STAILQ_FOREACH(cur, head, link) {
    566         fprintf(f, "%*sMultiple=", indent_level, "");
    567         if (!cur->multiple)
    568             fprintf(f, "nil (1)");
    569         else
    570             yasm_expr_print(cur->multiple, f);
    571         switch (cur->type) {
    572             case DV_EMPTY:
    573                 fprintf(f, "%*sEmpty\n", indent_level, "");
    574                 break;
    575             case DV_VALUE:
    576                 fprintf(f, "%*sValue:\n", indent_level, "");
    577                 yasm_value_print(&cur->data.val, f, indent_level+1);
    578                 break;
    579             case DV_RAW:
    580                 fprintf(f, "%*sLength=%lu\n", indent_level, "",
    581                         cur->data.raw.len);
    582                 fprintf(f, "%*sBytes=[", indent_level, "");
    583                 for (i=0; i<cur->data.raw.len; i++)
    584                     fprintf(f, "0x%02x, ", cur->data.raw.contents[i]);
    585                 fprintf(f, "]\n");
    586                 break;
    587             case DV_ULEB128:
    588                 fprintf(f, "%*sULEB128 value:\n", indent_level, "");
    589                 yasm_value_print(&cur->data.val, f, indent_level+1);
    590                 break;
    591             case DV_SLEB128:
    592                 fprintf(f, "%*sSLEB128 value:\n", indent_level, "");
    593                 yasm_value_print(&cur->data.val, f, indent_level+1);
    594                 break;
    595             case DV_RESERVE:
    596                 fprintf(f, "%*sReserved\n", indent_level, "");
    597                 break;
    598         }
    599     }
    600 }
    601