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 41 void 42 yasm_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 51 void 52 yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc) 53 { 54 } 55 56 int 57 yasm_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 65 int 66 yasm_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 74 int 75 yasm_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 85 void 86 yasm_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 95 yasm_bytecode * 96 yasm_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 114 yasm_section * 115 yasm_bc_get_section(yasm_bytecode *bc) 116 { 117 return bc->section; 118 } 119 120 void 121 yasm_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 141 void 142 yasm_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 155 void 156 yasm_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 172 void 173 yasm_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 * 200 yasm_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 219 unsigned long 220 yasm_bc_next_offset(yasm_bytecode *precbc) 221 { 222 return precbc->offset + precbc->len*precbc->mult_int; 223 } 224 225 int 226 yasm_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 237 int 238 yasm_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 283 int 284 yasm_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 * 301 yasm_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 352 int 353 yasm_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 374 const yasm_expr * 375 yasm_bc_get_multiple_expr(const yasm_bytecode *bc) 376 { 377 return bc->multiple; 378 } 379 380 yasm_insn * 381 yasm_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