• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
bc_data_destroy(void * contents)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
bc_data_print(const void * contents,FILE * f,int indent_level)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
bc_data_finalize(yasm_bytecode * bc,yasm_bytecode * prev_bc)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
bc_data_item_size(yasm_bytecode * bc)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
bc_data_calc_len(yasm_bytecode * bc,yasm_bc_add_span_func add_span,void * add_span_data)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
bc_data_tobytes(yasm_bytecode * bc,unsigned char ** bufp,unsigned char * bufstart,void * d,yasm_output_value_func output_value,yasm_output_reloc_func output_reloc)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 *
yasm_bc_create_data(yasm_datavalhead * datahead,unsigned int size,int append_zero,yasm_arch * arch,unsigned long line)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 *
yasm_bc_create_leb128(yasm_datavalhead * datahead,int sign,unsigned long line)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 *
yasm_dv_create_expr(yasm_expr * e)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 *
yasm_dv_create_raw(unsigned char * contents,unsigned long len)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 *
yasm_dv_create_reserve(void)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 *
yasm_dv_get_value(yasm_dataval * dv)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
yasm_dv_set_multiple(yasm_dataval * dv,yasm_expr * e)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
yasm_dv_get_multiple(yasm_dataval * dv,unsigned long * multiple)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
yasm_dvs_delete(yasm_datavalhead * headp)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 *
yasm_dvs_append(yasm_datavalhead * headp,yasm_dataval * dv)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
yasm_dvs_print(const yasm_datavalhead * head,FILE * f,int indent_level)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