123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- /*
- * Incbin bytecode
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- #include "util.h"
- #include "libyasm-stdint.h"
- #include "coretype.h"
- #include "linemap.h"
- #include "errwarn.h"
- #include "intnum.h"
- #include "expr.h"
- #include "value.h"
- #include "bytecode.h"
- #include "file.h"
- typedef struct bytecode_incbin {
- /*@only@*/ char *filename; /* file to include data from */
- const char *from; /* filename of what contained incbin */
- /* starting offset to read from (NULL=0) */
- /*@only@*/ /*@null@*/ yasm_expr *start;
- /* maximum number of bytes to read (NULL=no limit) */
- /*@only@*/ /*@null@*/ yasm_expr *maxlen;
- } bytecode_incbin;
- static void bc_incbin_destroy(void *contents);
- static void bc_incbin_print(const void *contents, FILE *f, int indent_level);
- static void bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
- static int bc_incbin_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data);
- static int bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
- static const yasm_bytecode_callback bc_incbin_callback = {
- bc_incbin_destroy,
- bc_incbin_print,
- bc_incbin_finalize,
- NULL,
- bc_incbin_calc_len,
- yasm_bc_expand_common,
- bc_incbin_tobytes,
- 0
- };
- static void
- bc_incbin_destroy(void *contents)
- {
- bytecode_incbin *incbin = (bytecode_incbin *)contents;
- yasm_xfree(incbin->filename);
- yasm_expr_destroy(incbin->start);
- yasm_expr_destroy(incbin->maxlen);
- yasm_xfree(contents);
- }
- static void
- bc_incbin_print(const void *contents, FILE *f, int indent_level)
- {
- const bytecode_incbin *incbin = (const bytecode_incbin *)contents;
- fprintf(f, "%*s_IncBin_\n", indent_level, "");
- fprintf(f, "%*sFilename=`%s'\n", indent_level, "",
- incbin->filename);
- fprintf(f, "%*sStart=", indent_level, "");
- if (!incbin->start)
- fprintf(f, "nil (0)");
- else
- yasm_expr_print(incbin->start, f);
- fprintf(f, "%*sMax Len=", indent_level, "");
- if (!incbin->maxlen)
- fprintf(f, "nil (unlimited)");
- else
- yasm_expr_print(incbin->maxlen, f);
- fprintf(f, "\n");
- }
- static void
- bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
- {
- bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
- yasm_value val;
- if (yasm_value_finalize_expr(&val, incbin->start, prev_bc, 0))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("start expression too complex"));
- else if (val.rel)
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("start expression not absolute"));
- incbin->start = val.abs;
- if (yasm_value_finalize_expr(&val, incbin->maxlen, prev_bc, 0))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("maximum length expression too complex"));
- else if (val.rel)
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("maximum length expression not absolute"));
- incbin->maxlen = val.abs;
- }
- static int
- bc_incbin_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
- {
- bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
- FILE *f;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
- unsigned long start = 0, maxlen = 0xFFFFFFFFUL, flen;
- /* Try to convert start to integer value */
- if (incbin->start) {
- num = yasm_expr_get_intnum(&incbin->start, 0);
- if (num)
- start = yasm_intnum_get_uint(num);
- if (!num) {
- /* FIXME */
- yasm_error_set(YASM_ERROR_NOT_IMPLEMENTED,
- N_("incbin does not yet understand non-constant"));
- return -1;
- }
- }
- /* Try to convert maxlen to integer value */
- if (incbin->maxlen) {
- num = yasm_expr_get_intnum(&incbin->maxlen, 0);
- if (num)
- maxlen = yasm_intnum_get_uint(num);
- if (!num) {
- /* FIXME */
- yasm_error_set(YASM_ERROR_NOT_IMPLEMENTED,
- N_("incbin does not yet understand non-constant"));
- return -1;
- }
- }
- /* Open file and determine its length */
- f = yasm_fopen_include(incbin->filename, incbin->from, "rb", NULL);
- if (!f) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to open file `%s'"),
- incbin->filename);
- return -1;
- }
- if (fseek(f, 0L, SEEK_END) < 0) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to seek on file `%s'"),
- incbin->filename);
- return -1;
- }
- flen = (unsigned long)ftell(f);
- fclose(f);
- /* Compute length of incbin from start, maxlen, and len */
- if (start > flen) {
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("`incbin': start past end of file `%s'"),
- incbin->filename);
- start = flen;
- }
- flen -= start;
- if (incbin->maxlen)
- if (maxlen < flen)
- flen = maxlen;
- bc->len += flen;
- return 0;
- }
- static int
- bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
- {
- bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
- FILE *f;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
- unsigned long start = 0;
- /* Convert start to integer value */
- if (incbin->start) {
- num = yasm_expr_get_intnum(&incbin->start, 0);
- if (!num)
- yasm_internal_error(
- N_("could not determine start in bc_tobytes_incbin"));
- start = yasm_intnum_get_uint(num);
- }
- /* Open file */
- f = yasm_fopen_include(incbin->filename, incbin->from, "rb", NULL);
- if (!f) {
- yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to open file `%s'"),
- incbin->filename);
- return 1;
- }
- /* Seek to start of data */
- if (fseek(f, (long)start, SEEK_SET) < 0) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to seek on file `%s'"),
- incbin->filename);
- fclose(f);
- return 1;
- }
- /* Read len bytes */
- if (fread(*bufp, 1, (size_t)bc->len, f) < (size_t)bc->len) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to read %lu bytes from file `%s'"),
- bc->len, incbin->filename);
- fclose(f);
- return 1;
- }
- *bufp += bc->len;
- fclose(f);
- return 0;
- }
- yasm_bytecode *
- yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen,
- yasm_linemap *linemap, unsigned long line)
- {
- bytecode_incbin *incbin = yasm_xmalloc(sizeof(bytecode_incbin));
- unsigned long xline;
- /* Find from filename based on line number */
- yasm_linemap_lookup(linemap, line, &incbin->from, &xline);
- /*@-mustfree@*/
- incbin->filename = filename;
- incbin->start = start;
- incbin->maxlen = maxlen;
- /*@=mustfree@*/
- return yasm_bc_create_common(&bc_incbin_callback, incbin, line);
- }
|