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
41struct 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
59typedef struct bytecode_data {
60    /* converted data (linked list) */
61    yasm_datavalhead datahead;
62
63    int item_size;
64} bytecode_data;
65
66static void bc_data_destroy(void *contents);
67static void bc_data_print(const void *contents, FILE *f, int indent_level);
68static void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
69static int bc_data_item_size(yasm_bytecode *bc);
70static int bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
71                            void *add_span_data);
72static 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
77static 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
89static void
90bc_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
97static void
98bc_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
106static void
107bc_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
155static int
156bc_data_item_size(yasm_bytecode *bc)
157{
158    bytecode_data *bc_data = (bytecode_data *)bc->contents;
159    return bc_data->item_size;
160}
161
162static int
163bc_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
205static int
206bc_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
262yasm_bytecode *
263yasm_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
424yasm_bytecode *
425yasm_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
447yasm_dataval *
448yasm_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
459yasm_dataval *
460yasm_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
472yasm_dataval *
473yasm_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
483yasm_value *
484yasm_dv_get_value(yasm_dataval *dv)
485{
486    if (dv->type != DV_VALUE)
487        return NULL;
488    return &dv->data.val;
489}
490
491void
492yasm_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
501int
502yasm_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
523void
524yasm_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
549yasm_dataval *
550yasm_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
559void
560yasm_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