2 * Data (and LEB128) bytecode
4 * Copyright (C) 2001-2007 Peter Johnson
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
29 #include "libyasm-stdint.h"
42 /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link;
44 enum { DV_EMPTY, DV_VALUE, DV_RAW, DV_ULEB128, DV_SLEB128, DV_RESERVE }
50 /*@only@*/ unsigned char *contents;
55 /* number of times data is repeated, NULL=1. */
56 /*@only@*/ /*@null@*/ yasm_expr *multiple;
59 typedef struct bytecode_data {
60 /* converted data (linked list) */
61 yasm_datavalhead datahead;
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,
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);
77 static const yasm_bytecode_callback bc_data_callback = {
83 yasm_bc_expand_common,
90 bc_data_destroy(void *contents)
92 bytecode_data *bc_data = (bytecode_data *)contents;
93 yasm_dvs_delete(&bc_data->datahead);
98 bc_data_print(const void *contents, FILE *f, int indent_level)
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);
107 bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
109 bytecode_data *bc_data = (bytecode_data *)bc->contents;
113 /* Convert values from simple expr to value. */
114 STAILQ_FOREACH(dv, &bc_data->datahead, link) {
117 if (yasm_value_finalize(&dv->data.val, prev_bc)) {
118 yasm_error_set(YASM_ERROR_TOO_COMPLEX,
119 N_("data expression too complex"));
125 intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
127 yasm_error_set(YASM_ERROR_NOT_CONSTANT,
128 N_("LEB128 requires constant values"));
131 /* Warn for negative values in unsigned environment.
132 * This could be an error instead: the likelihood this is
133 * desired is very low!
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"));
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"));
148 yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
149 N_("multiple expression not absolute"));
150 dv->multiple = val.abs;
156 bc_data_item_size(yasm_bytecode *bc)
158 bytecode_data *bc_data = (bytecode_data *)bc->contents;
159 return bc_data->item_size;
163 bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
166 bytecode_data *bc_data = (bytecode_data *)bc->contents;
169 unsigned long len = 0;
170 unsigned long multiple;
172 /* Count up element sizes, rounding up string length. */
173 STAILQ_FOREACH(dv, &bc_data->datahead, link) {
179 len = dv->data.val.size/8;
182 len = dv->data.raw.len;
186 intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
188 yasm_internal_error(N_("non-constant in data_tobytes"));
189 len = yasm_intnum_size_leb128(intn, dv->type == DV_SLEB128);
192 len = dv->data.val.size/8;
196 if (!yasm_dv_get_multiple(dv, &multiple))
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)
211 bytecode_data *bc_data = (bytecode_data *)bc->contents;
214 unsigned int val_len;
215 unsigned long multiple, i;
217 STAILQ_FOREACH(dv, &bc_data->datahead, link) {
218 if (yasm_dv_get_multiple(dv, &multiple) || multiple == 0)
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,
234 for (i=0; i<multiple; i++) {
235 memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len);
236 *bufp += dv->data.raw.len;
241 intn = yasm_expr_get_intnum(&dv->data.val.abs, 234);
243 yasm_internal_error(N_("non-constant in data_tobytes"));
244 for (i=0; i<multiple; i++) {
246 yasm_intnum_get_leb128(intn, *bufp,
247 dv->type == DV_SLEB128);
250 val_len = dv->data.val.size/8;
251 for (i=0; i<multiple; i++) {
252 memset(*bufp, 0, val_len);
263 yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
264 int append_zero, yasm_arch *arch, unsigned long line)
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;
270 unsigned long len = 0, rlen, i;
273 yasm_dvs_initialize(&data->datahead);
274 data->item_size = size;
276 /* Prescan input data for length, etc. Careful: this needs to be
277 * precisely paired with the second loop.
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);
292 intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
293 if (intn && dv->type == DV_VALUE && (arch || size == 1))
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);
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);
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;
314 rlen = dv->data.raw.len;
315 /* find count, rounding up to nearest multiple of size */
316 rlen = (rlen + size - 1) / size;
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;
336 /* Create final dataval for any trailing length */
338 dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
339 STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
342 /* Second iteration: copy data and delete input datavals. */
343 dv = STAILQ_FIRST(datahead);
344 dvo = STAILQ_FIRST(&data->datahead);
347 if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
348 dvo = STAILQ_NEXT(dvo, link);
357 intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
358 if (intn && dv->type == DV_VALUE && (arch || size == 1)) {
360 yasm_intnum_get_sized(intn,
361 &dvo->data.raw.contents[len],
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);
369 } else if (intn && dv->type == DV_ULEB128) {
370 len += yasm_intnum_get_leb128(intn,
371 &dvo->data.raw.contents[len],
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],
378 yasm_value_delete(&dv->data.val);
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);
390 rlen = dv->data.raw.len;
391 memcpy(&dvo->data.raw.contents[len], dv->data.raw.contents,
393 yasm_xfree(dv->data.raw.contents);
395 /* pad with 0's to nearest multiple of size */
399 for (i=0; i<rlen; i++)
400 dvo->data.raw.contents[len++] = 0;
404 memset(&dvo->data.raw.contents[len], 0, size);
409 if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
410 dvo = STAILQ_NEXT(dvo, link);
415 dvo->data.raw.contents[len++] = 0;
416 dv2 = STAILQ_NEXT(dv, link);
425 yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
429 /* Convert all values into LEB type, error on strings/raws */
430 STAILQ_FOREACH(dv, datahead, link) {
433 dv->type = sign ? DV_SLEB128 : DV_ULEB128;
436 yasm_error_set(YASM_ERROR_VALUE,
437 N_("LEB128 does not allow string constants"));
444 return yasm_bc_create_data(datahead, 0, 0, 0, line);
448 yasm_dv_create_expr(yasm_expr *e)
450 yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
452 retval->type = DV_VALUE;
453 yasm_value_initialize(&retval->data.val, e, 0);
454 retval->multiple = NULL;
460 yasm_dv_create_raw(unsigned char *contents, unsigned long len)
462 yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
464 retval->type = DV_RAW;
465 retval->data.raw.contents = contents;
466 retval->data.raw.len = len;
467 retval->multiple = NULL;
473 yasm_dv_create_reserve(void)
475 yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
477 retval->type = DV_RESERVE;
478 retval->multiple = NULL;
484 yasm_dv_get_value(yasm_dataval *dv)
486 if (dv->type != DV_VALUE)
488 return &dv->data.val;
492 yasm_dv_set_multiple(yasm_dataval *dv, yasm_expr *e)
495 dv->multiple = yasm_expr_create_tree( dv->multiple, YASM_EXPR_MUL, e,
502 yasm_dv_get_multiple(yasm_dataval *dv, unsigned long *multiple)
504 /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
508 num = yasm_expr_get_intnum(&dv->multiple, 0);
510 yasm_error_set(YASM_ERROR_VALUE,
511 N_("could not determine multiple"));
514 if (yasm_intnum_sign(num) < 0) {
515 yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
518 *multiple = yasm_intnum_get_uint(num);
524 yasm_dvs_delete(yasm_datavalhead *headp)
526 yasm_dataval *cur, *next;
528 cur = STAILQ_FIRST(headp);
530 next = STAILQ_NEXT(cur, link);
533 yasm_value_delete(&cur->data.val);
536 yasm_xfree(cur->data.raw.contents);
542 yasm_expr_destroy(cur->multiple);
550 yasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv)
553 STAILQ_INSERT_TAIL(headp, dv, link);
556 return (yasm_dataval *)NULL;
560 yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
565 STAILQ_FOREACH(cur, head, link) {
566 fprintf(f, "%*sMultiple=", indent_level, "");
568 fprintf(f, "nil (1)");
570 yasm_expr_print(cur->multiple, f);
573 fprintf(f, "%*sEmpty\n", indent_level, "");
576 fprintf(f, "%*sValue:\n", indent_level, "");
577 yasm_value_print(&cur->data.val, f, indent_level+1);
580 fprintf(f, "%*sLength=%lu\n", indent_level, "",
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]);
588 fprintf(f, "%*sULEB128 value:\n", indent_level, "");
589 yasm_value_print(&cur->data.val, f, indent_level+1);
592 fprintf(f, "%*sSLEB128 value:\n", indent_level, "");
593 yasm_value_print(&cur->data.val, f, indent_level+1);
596 fprintf(f, "%*sReserved\n", indent_level, "");