1/* 2 * Bytecode utility functions 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#include "symrec.h" 37 38#include "bytecode.h" 39 40 41void 42yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e) 43{ 44 if (bc->multiple) 45 bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL, e, 46 e->line); 47 else 48 bc->multiple = e; 49} 50 51void 52yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc) 53{ 54} 55 56int 57yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span, 58 void *add_span_data) 59{ 60 yasm_internal_error(N_("bytecode length cannot be calculated")); 61 /*@unreached@*/ 62 return 0; 63} 64 65int 66yasm_bc_expand_common(yasm_bytecode *bc, int span, long old_val, long new_val, 67 /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres) 68{ 69 yasm_internal_error(N_("bytecode does not have any dependent spans")); 70 /*@unreached@*/ 71 return 0; 72} 73 74int 75yasm_bc_tobytes_common(yasm_bytecode *bc, unsigned char **buf, 76 unsigned char *bufstart, void *d, 77 yasm_output_value_func output_value, 78 /*@null@*/ yasm_output_reloc_func output_reloc) 79{ 80 yasm_internal_error(N_("bytecode cannot be converted to bytes")); 81 /*@unreached@*/ 82 return 0; 83} 84 85void 86yasm_bc_transform(yasm_bytecode *bc, const yasm_bytecode_callback *callback, 87 void *contents) 88{ 89 if (bc->callback) 90 bc->callback->destroy(bc->contents); 91 bc->callback = callback; 92 bc->contents = contents; 93} 94 95yasm_bytecode * 96yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents, 97 unsigned long line) 98{ 99 yasm_bytecode *bc = yasm_xmalloc(sizeof(yasm_bytecode)); 100 101 bc->callback = callback; 102 bc->section = NULL; 103 bc->multiple = (yasm_expr *)NULL; 104 bc->len = 0; 105 bc->mult_int = 1; 106 bc->line = line; 107 bc->offset = ~0UL; /* obviously incorrect / uninitialized value */ 108 bc->symrecs = NULL; 109 bc->contents = contents; 110 111 return bc; 112} 113 114yasm_section * 115yasm_bc_get_section(yasm_bytecode *bc) 116{ 117 return bc->section; 118} 119 120void 121yasm_bc__add_symrec(yasm_bytecode *bc, yasm_symrec *sym) 122{ 123 if (!bc->symrecs) { 124 bc->symrecs = yasm_xmalloc(2*sizeof(yasm_symrec *)); 125 bc->symrecs[0] = sym; 126 bc->symrecs[1] = NULL; 127 } else { 128 /* Very inefficient implementation for large numbers of symbols. But 129 * that would be very unusual, so use the simple algorithm instead. 130 */ 131 size_t count = 1; 132 while (bc->symrecs[count]) 133 count++; 134 bc->symrecs = yasm_xrealloc(bc->symrecs, 135 (count+2)*sizeof(yasm_symrec *)); 136 bc->symrecs[count] = sym; 137 bc->symrecs[count+1] = NULL; 138 } 139} 140 141void 142yasm_bc_destroy(yasm_bytecode *bc) 143{ 144 if (!bc) 145 return; 146 147 if (bc->callback) 148 bc->callback->destroy(bc->contents); 149 yasm_expr_destroy(bc->multiple); 150 if (bc->symrecs) 151 yasm_xfree(bc->symrecs); 152 yasm_xfree(bc); 153} 154 155void 156yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level) 157{ 158 if (!bc->callback) 159 fprintf(f, "%*s_Empty_\n", indent_level, ""); 160 else 161 bc->callback->print(bc->contents, f, indent_level); 162 fprintf(f, "%*sMultiple=", indent_level, ""); 163 if (!bc->multiple) 164 fprintf(f, "nil (1)"); 165 else 166 yasm_expr_print(bc->multiple, f); 167 fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len); 168 fprintf(f, "%*sLine Index=%lu\n", indent_level, "", bc->line); 169 fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset); 170} 171 172void 173yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) 174{ 175 if (bc->callback) 176 bc->callback->finalize(bc, prev_bc); 177 if (bc->multiple) { 178 yasm_value val; 179 180 if (yasm_value_finalize_expr(&val, bc->multiple, prev_bc, 0)) 181 yasm_error_set(YASM_ERROR_TOO_COMPLEX, 182 N_("multiple expression too complex")); 183 else if (val.rel) 184 yasm_error_set(YASM_ERROR_NOT_ABSOLUTE, 185 N_("multiple expression not absolute")); 186 /* Finalize creates NULL output if value=0, but bc->multiple is NULL 187 * if value=1 (this difference is to make the common case small). 188 * However, this means we need to set bc->multiple explicitly to 0 189 * here if val.abs is NULL. 190 */ 191 if (val.abs) 192 bc->multiple = val.abs; 193 else 194 bc->multiple = yasm_expr_create_ident( 195 yasm_expr_int(yasm_intnum_create_uint(0)), bc->line); 196 } 197} 198 199/*@null@*/ yasm_intnum * 200yasm_calc_bc_dist(yasm_bytecode *precbc1, yasm_bytecode *precbc2) 201{ 202 unsigned long dist2, dist1; 203 yasm_intnum *intn; 204 205 if (precbc1->section != precbc2->section) 206 return NULL; 207 208 dist1 = yasm_bc_next_offset(precbc1); 209 dist2 = yasm_bc_next_offset(precbc2); 210 if (dist2 < dist1) { 211 intn = yasm_intnum_create_uint(dist1 - dist2); 212 yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL); 213 return intn; 214 } 215 dist2 -= dist1; 216 return yasm_intnum_create_uint(dist2); 217} 218 219unsigned long 220yasm_bc_next_offset(yasm_bytecode *precbc) 221{ 222 return precbc->offset + precbc->len*precbc->mult_int; 223} 224 225int 226yasm_bc_elem_size(yasm_bytecode *bc) 227{ 228 if (!bc->callback) { 229 yasm_internal_error(N_("got empty bytecode in yasm_bc_elem_size")); 230 return 0; 231 } else if (!bc->callback->elem_size) 232 return 0; 233 else 234 return bc->callback->elem_size(bc); 235} 236 237int 238yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, 239 void *add_span_data) 240{ 241 int retval = 0; 242 243 bc->len = 0; 244 245 if (!bc->callback) 246 yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len")); 247 else 248 retval = bc->callback->calc_len(bc, add_span, add_span_data); 249 250 /* Check for multiples */ 251 bc->mult_int = 1; 252 if (bc->multiple) { 253 /*@dependent@*/ /*@null@*/ const yasm_intnum *num; 254 255 num = yasm_expr_get_intnum(&bc->multiple, 0); 256 if (num) { 257 if (yasm_intnum_sign(num) < 0) { 258 yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative")); 259 retval = -1; 260 } else 261 bc->mult_int = yasm_intnum_get_int(num); 262 } else { 263 if (yasm_expr__contains(bc->multiple, YASM_EXPR_FLOAT)) { 264 yasm_error_set(YASM_ERROR_VALUE, 265 N_("expression must not contain floating point value")); 266 retval = -1; 267 } else { 268 yasm_value value; 269 yasm_value_initialize(&value, bc->multiple, 0); 270 add_span(add_span_data, bc, 0, &value, 0, 0); 271 bc->mult_int = 0; /* assume 0 to start */ 272 } 273 } 274 } 275 276 /* If we got an error somewhere along the line, clear out any calc len */ 277 if (retval < 0) 278 bc->len = 0; 279 280 return retval; 281} 282 283int 284yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val, 285 /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres) 286{ 287 if (span == 0) { 288 bc->mult_int = new_val; 289 return 1; 290 } 291 if (!bc->callback) { 292 yasm_internal_error(N_("got empty bytecode in yasm_bc_expand")); 293 /*@unreached@*/ 294 return -1; 295 } else 296 return bc->callback->expand(bc, span, old_val, new_val, neg_thres, 297 pos_thres); 298} 299 300/*@null@*/ /*@only@*/ unsigned char * 301yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize, 302 /*@out@*/ int *gap, void *d, 303 yasm_output_value_func output_value, 304 /*@null@*/ yasm_output_reloc_func output_reloc) 305 /*@sets *buf@*/ 306{ 307 /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL; 308 unsigned char *bufstart; 309 unsigned char *origbuf, *destbuf; 310 long i; 311 int error = 0; 312 313 long mult; 314 if (yasm_bc_get_multiple(bc, &mult, 1) || mult == 0) { 315 *bufsize = 0; 316 return NULL; 317 } 318 bc->mult_int = mult; 319 320 /* special case for reserve bytecodes */ 321 if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) { 322 *bufsize = bc->len*bc->mult_int; 323 *gap = 1; 324 return NULL; /* we didn't allocate a buffer */ 325 } 326 *gap = 0; 327 328 if (*bufsize < bc->len*bc->mult_int) { 329 mybuf = yasm_xmalloc(bc->len*bc->mult_int); 330 destbuf = mybuf; 331 } else 332 destbuf = buf; 333 bufstart = destbuf; 334 335 *bufsize = bc->len*bc->mult_int; 336 337 if (!bc->callback) 338 yasm_internal_error(N_("got empty bytecode in bc_tobytes")); 339 else for (i=0; i<bc->mult_int; i++) { 340 origbuf = destbuf; 341 error = bc->callback->tobytes(bc, &destbuf, bufstart, d, output_value, 342 output_reloc); 343 344 if (!error && ((unsigned long)(destbuf - origbuf) != bc->len)) 345 yasm_internal_error( 346 N_("written length does not match optimized length")); 347 } 348 349 return mybuf; 350} 351 352int 353yasm_bc_get_multiple(yasm_bytecode *bc, long *multiple, int calc_bc_dist) 354{ 355 /*@dependent@*/ /*@null@*/ const yasm_intnum *num; 356 357 *multiple = 1; 358 if (bc->multiple) { 359 num = yasm_expr_get_intnum(&bc->multiple, calc_bc_dist); 360 if (!num) { 361 yasm_error_set(YASM_ERROR_VALUE, 362 N_("could not determine multiple")); 363 return 1; 364 } 365 if (yasm_intnum_sign(num) < 0) { 366 yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative")); 367 return 1; 368 } 369 *multiple = yasm_intnum_get_int(num); 370 } 371 return 0; 372} 373 374const yasm_expr * 375yasm_bc_get_multiple_expr(const yasm_bytecode *bc) 376{ 377 return bc->multiple; 378} 379 380yasm_insn * 381yasm_bc_get_insn(yasm_bytecode *bc) 382{ 383 if (bc->callback->special != YASM_BC_SPECIAL_INSN) 384 return NULL; 385 return (yasm_insn *)bc->contents; 386} 387