Beispiel #1
0
/* Invoke the c preprocessor to generate dependency info. */
static void
cpp_generate_deps(yasm_preproc_cpp *pp)
{
    char *cmdline;

    cmdline = cpp_build_cmdline(pp, "-M");

#ifdef HAVE_POPEN
    pp->f_deps = popen(cmdline, "r");
    if (!pp->f_deps)
        yasm__fatal( N_("Failed to execute preprocessor") );
#else
    yasm__fatal( N_("Cannot execute preprocessor, no popen available") );
#endif

    yasm_xfree(cmdline);
}
Beispiel #2
0
static void *
def_xmalloc(size_t size)
{
    void *newmem;

    if (size == 0)
        size = 1;
    newmem = malloc(size);
    if (!newmem)
        yasm__fatal(N_("out of memory"));

    return newmem;
}
Beispiel #3
0
static void *
def_xcalloc(size_t nelem, size_t elsize)
{
    void *newmem;

    if (nelem == 0 || elsize == 0)
        nelem = elsize = 1;

    newmem = calloc(nelem, elsize);
    if (!newmem)
        yasm__fatal(N_("out of memory"));

    return newmem;
}
Beispiel #4
0
static void *
def_xrealloc(void *oldmem, size_t size)
{
    void *newmem;

    if (size == 0)
        size = 1;
    if (!oldmem)
        newmem = malloc(size);
    else
        newmem = realloc(oldmem, size);
    if (!newmem)
        yasm__fatal(N_("out of memory"));

    return newmem;
}
Beispiel #5
0
static void
cpp_preproc_destroy(yasm_preproc *preproc)
{
    yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;

    if (pp->f) {
#ifdef HAVE_POPEN
        if (pclose(pp->f) != 0)
            yasm__fatal( N_("Preprocessor exited with failure") );
#endif
    }

    cpp_destroy_args(pp);

    yasm_xfree(pp->filename);
    yasm_xfree(pp);
}
Beispiel #6
0
static yasm_preproc *
raw_preproc_create(const char *in_filename, yasm_symtab *symtab,
                   yasm_linemap *lm, yasm_errwarns *errwarns)
{
    FILE *f;
    yasm_preproc_raw *preproc_raw = yasm_xmalloc(sizeof(yasm_preproc_raw));

    if (strcmp(in_filename, "-") != 0) {
        f = fopen(in_filename, "r");
        if (!f)
            yasm__fatal( N_("Could not open input file") );
    }
    else
        f = stdin;

    preproc_raw->preproc.module = &yasm_raw_LTX_preproc;
    preproc_raw->in = f;
    preproc_raw->cur_lm = lm;
    preproc_raw->errwarns = errwarns;

    return (yasm_preproc *)preproc_raw;
}
Beispiel #7
0
static int
value_finalize_scan(yasm_value *value, yasm_expr *e,
                    /*@null@*/ yasm_bytecode *expr_precbc, int ssym_not_ok)
{
    int i;
    /*@dependent@*/ yasm_section *sect;
    /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;

    unsigned long shamt;    /* for SHR */

    /* Yes, this has a maximum upper bound on 32 terms, based on an
     * "insane number of terms" (and ease of implementation) WAG.
     * The right way to do this would be a stack-based alloca, but that's
     * not ISO C.  We really don't want to malloc here as this function is
     * hit a lot!
     *
     * This is a bitmask to keep things small, as this is a recursive
     * routine and we don't want to eat up stack space.
     */
    unsigned long used;     /* for ADD */

    /* Thanks to this running after a simplify, we don't need to iterate
     * down through IDENTs or handle SUB.
     *
     * We scan for a single symrec, gathering info along the way.  After
     * we've found the symrec, we keep scanning but error if we find
     * another one.  We pull out the single symrec and any legal operations
     * performed on it.
     *
     * Also, if we find a float anywhere, we don't allow mixing of a single
     * symrec with it.
     */
    switch (e->op) {
        case YASM_EXPR_ADD:
            /* Okay for single symrec anywhere in expr.
             * Check for single symrec anywhere.
             * Handle symrec-symrec by checking for (-1*symrec)
             * and symrec term pairs (where both symrecs are in the same
             * segment).
             */
            if (e->numterms > 32)
                yasm__fatal(N_("expression on line %d has too many add terms;"
                               " internal limit of 32"), e->line);

            used = 0;

            for (i=0; i<e->numterms; i++) {
                int j;
                yasm_expr *sube;
                yasm_intnum *intn;
                yasm_symrec *sym;
                /*@dependent@*/ yasm_section *sect2;
                /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2;

                /* First look for an (-1*symrec) term */
                if (e->terms[i].type != YASM_EXPR_EXPR)
                    continue;
                sube = e->terms[i].data.expn;

                if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) {
                    /* recurse instead */
                    if (value_finalize_scan(value, sube, expr_precbc,
                                            ssym_not_ok))
                        return 1;
                    continue;
                }

                if (sube->terms[0].type == YASM_EXPR_INT &&
                    sube->terms[1].type == YASM_EXPR_SYM) {
                    intn = sube->terms[0].data.intn;
                    sym = sube->terms[1].data.sym;
                } else if (sube->terms[0].type == YASM_EXPR_SYM &&
                           sube->terms[1].type == YASM_EXPR_INT) {
                    sym = sube->terms[0].data.sym;
                    intn = sube->terms[1].data.intn;
                } else {
                    if (value_finalize_scan(value, sube, expr_precbc,
                                            ssym_not_ok))
                        return 1;
                    continue;
                }

                if (!yasm_intnum_is_neg1(intn)) {
                    if (value_finalize_scan(value, sube, expr_precbc,
                                            ssym_not_ok))
                        return 1;
                    continue;
                }

                /* Look for the same symrec term; even if both are external,
                 * they should cancel out.
                 */
                for (j=0; j<e->numterms; j++) {
                    if (e->terms[j].type == YASM_EXPR_SYM
                        && e->terms[j].data.sym == sym
                        && (used & (1<<j)) == 0) {
                        /* Mark as used */
                        used |= 1<<j;

                        /* Replace both symrec portions with 0 */
                        yasm_expr_destroy(sube);
                        e->terms[i].type = YASM_EXPR_INT;
                        e->terms[i].data.intn = yasm_intnum_create_uint(0);
                        e->terms[j].type = YASM_EXPR_INT;
                        e->terms[j].data.intn = yasm_intnum_create_uint(0);

                        break;  /* stop looking */
                    }
                }
                if (j != e->numterms)
                    continue;

                if (!yasm_symrec_get_label(sym, &precbc)) {
                    if (value_finalize_scan(value, sube, expr_precbc,
                                            ssym_not_ok))
                        return 1;
                    continue;
                }
                sect2 = yasm_bc_get_section(precbc);

                /* Now look for a unused symrec term in the same segment */
                for (j=0; j<e->numterms; j++) {
                    if (e->terms[j].type == YASM_EXPR_SYM
                        && yasm_symrec_get_label(e->terms[j].data.sym,
                                                 &precbc2)
                        && (sect = yasm_bc_get_section(precbc2))
                        && sect == sect2
                        && (used & (1<<j)) == 0) {
                        /* Mark as used */
                        used |= 1<<j;
                        break;  /* stop looking */
                    }
                }

                /* We didn't match in the same segment.  If the
                 * -1*symrec is actually -1*curpos, we can match
                 * unused symrec terms in other segments and generate
                 * a curpos-relative reloc.
                 *
                 * Similarly, handle -1*symrec in other segment via the
                 * following transformation:
                 * other-this = (other-.)+(.-this)
                 * We can only do this transformation if "this" is in
                 * this expr's segment.
                 *
                 * Don't do this if we've already become curpos-relative.
                 * The unmatched symrec will be caught below.
                 */
                if (j == e->numterms && !value->curpos_rel
                    && (yasm_symrec_is_curpos(sym)
                        || (expr_precbc
                            && sect2 == yasm_bc_get_section(expr_precbc)))) {
                    for (j=0; j<e->numterms; j++) {
                        if (e->terms[j].type == YASM_EXPR_SYM
                            && !yasm_symrec_get_equ(e->terms[j].data.sym)
                            && !yasm_symrec_is_special(e->terms[j].data.sym)
                            && (used & (1<<j)) == 0) {
                            /* Mark as used */
                            used |= 1<<j;
                            /* Mark value as curpos-relative */
                            if (value->rel || ssym_not_ok)
                                return 1;
                            value->rel = e->terms[j].data.sym;
                            value->curpos_rel = 1;
                            if (yasm_symrec_is_curpos(sym)) {
                                /* Replace both symrec portions with 0 */
                                yasm_expr_destroy(sube);
                                e->terms[i].type = YASM_EXPR_INT;
                                e->terms[i].data.intn =
                                    yasm_intnum_create_uint(0);
                                e->terms[j].type = YASM_EXPR_INT;
                                e->terms[j].data.intn =
                                    yasm_intnum_create_uint(0);
                            } else {
                                /* Replace positive portion with curpos */
                                yasm_object *object =
                                    yasm_section_get_object(sect2);
                                yasm_symtab *symtab = object->symtab;
                                e->terms[j].data.sym =
                                    yasm_symtab_define_curpos
                                    (symtab, ".", expr_precbc, e->line);
                            }
                            break;      /* stop looking */
                        }
                    }
                }


                if (j == e->numterms)
                    return 1;   /* We didn't find a match! */
            }

            /* Look for unmatched symrecs.  If we've already found one or
             * we don't WANT to find one, error out.
             */
            for (i=0; i<e->numterms; i++) {
                if (e->terms[i].type == YASM_EXPR_SYM
                    && (used & (1<<i)) == 0) {
                    if (value->rel || ssym_not_ok)
                        return 1;
                    value->rel = e->terms[i].data.sym;
                    /* and replace with 0 */
                    e->terms[i].type = YASM_EXPR_INT;
                    e->terms[i].data.intn = yasm_intnum_create_uint(0);
                }
            }
            break;
        case YASM_EXPR_SHR:
            /* Okay for single symrec in LHS and constant on RHS.
             * Single symrecs are not okay on RHS.
             * If RHS is non-constant, don't allow single symrec on LHS.
             * XXX: should rshift be an expr instead??
             */

            /* Check for single sym on LHS */
            if (e->terms[0].type != YASM_EXPR_SYM)
                break;

            /* If we already have a sym, we can't take another one */
            if (value->rel || ssym_not_ok)
                return 1;

            /* RHS must be a positive integer */
            if (e->terms[1].type != YASM_EXPR_INT)
                return 1;       /* can't shift sym by non-constant integer */
            shamt = yasm_intnum_get_uint(e->terms[1].data.intn);
            if ((shamt + value->rshift) > YASM_VALUE_RSHIFT_MAX)
                return 1;       /* total shift would be too large */

            /* Update value */
            value->rshift += shamt;
            value->rel = e->terms[0].data.sym;

            /* Replace symbol with 0 */
            e->terms[0].type = YASM_EXPR_INT;
            e->terms[0].data.intn = yasm_intnum_create_uint(0);

            /* Just leave SHR in place */
            break;
        case YASM_EXPR_SEG:
            /* Okay for single symrec (can only be done once).
             * Not okay for anything BUT a single symrec as an immediate
             * child.
             */
            if (e->terms[0].type != YASM_EXPR_SYM)
                return 1;

            if (value->seg_of)
                return 1;       /* multiple SEG not legal */
            value->seg_of = 1;

            if (value->rel || ssym_not_ok)
                return 1;       /* got a relative portion somewhere else? */
            value->rel = e->terms[0].data.sym;

            /* replace with ident'ed 0 */
            e->op = YASM_EXPR_IDENT;
            e->terms[0].type = YASM_EXPR_INT;
            e->terms[0].data.intn = yasm_intnum_create_uint(0);
            break;
        case YASM_EXPR_WRT:
            /* Okay for single symrec in LHS and either a register or single
             * symrec (as an immediate child) on RHS.
             * If a single symrec on RHS, can only be done once.
             * WRT reg is left in expr for arch to look at.
             */

            /* Handle RHS */
            switch (e->terms[1].type) {
                case YASM_EXPR_SYM:
                    if (value->wrt)
                        return 1;
                    value->wrt = e->terms[1].data.sym;
                    /* and drop the WRT portion */
                    e->op = YASM_EXPR_IDENT;
                    e->numterms = 1;
                    break;
                case YASM_EXPR_REG:
                    break;  /* ignore */
                default:
                    return 1;
            }

            /* Handle LHS */
            switch (e->terms[0].type) {
                case YASM_EXPR_SYM:
                    if (value->rel || ssym_not_ok)
                        return 1;
                    value->rel = e->terms[0].data.sym;
                    /* and replace with 0 */
                    e->terms[0].type = YASM_EXPR_INT;
                    e->terms[0].data.intn = yasm_intnum_create_uint(0);
                    break;
                case YASM_EXPR_EXPR:
                    /* recurse */
                    return value_finalize_scan(value, e->terms[0].data.expn,
                                               expr_precbc, ssym_not_ok);
                default:
                    break;  /* ignore */
            }

            break;
        default:
            /* Single symrec not allowed anywhere */
            for (i=0; i<e->numterms; i++) {
                switch (e->terms[i].type) {
                    case YASM_EXPR_SYM:
                        return 1;
                    case YASM_EXPR_EXPR:
                        /* recurse */
                        return value_finalize_scan(value,
                                                   e->terms[i].data.expn,
                                                   expr_precbc, 1);
                    default:
                        break;
                }
            }
            break;
    }

    return 0;
}
Beispiel #8
0
static void
xdf_objfmt_output(yasm_object *object, FILE *f, int all_syms,
                  yasm_errwarns *errwarns)
{
    yasm_objfmt_xdf *objfmt_xdf = (yasm_objfmt_xdf *)object->objfmt;
    xdf_objfmt_output_info info;
    unsigned char *localbuf;
    unsigned long symtab_count = 0;

    info.object = object;
    info.objfmt_xdf = objfmt_xdf;
    info.errwarns = errwarns;
    info.f = f;
    info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);

    /* Allocate space for headers by seeking forward */
    if (fseek(f, (long)(16+40*(objfmt_xdf->parse_scnum)), SEEK_SET) < 0) {
        yasm__fatal(N_("could not seek on output file"));
        /*@notreached@*/
        return;
    }

    /* Get number of symbols */
    info.indx = 0;
    info.all_syms = 1;  /* force all syms into symbol table */
    yasm_symtab_traverse(object->symtab, &info, xdf_objfmt_count_sym);
    symtab_count = info.indx;

    /* Get file offset of start of string table */
    info.strtab_offset = 16+40*(objfmt_xdf->parse_scnum)+16*symtab_count;

    /* Output symbol table */
    yasm_symtab_traverse(object->symtab, &info, xdf_objfmt_output_sym);

    /* Output string table */
    yasm_symtab_traverse(object->symtab, &info, xdf_objfmt_output_str);

    /* Section data/relocs */
    if (yasm_object_sections_traverse(object, &info,
                                      xdf_objfmt_output_section))
        return;

    /* Write headers */
    if (fseek(f, 0, SEEK_SET) < 0) {
        yasm__fatal(N_("could not seek on output file"));
        /*@notreached@*/
        return;
    }

    localbuf = info.buf;
    YASM_WRITE_32_L(localbuf, XDF_MAGIC);       /* magic number */
    YASM_WRITE_32_L(localbuf, objfmt_xdf->parse_scnum); /* number of sects */
    YASM_WRITE_32_L(localbuf, symtab_count);            /* number of symtabs */
    /* size of sect headers + symbol table + strings */
    YASM_WRITE_32_L(localbuf, info.strtab_offset-16);
    fwrite(info.buf, 16, 1, f);

    yasm_object_sections_traverse(object, &info, xdf_objfmt_output_secthead);

    yasm_xfree(info.buf);
}
Beispiel #9
0
static int
xdf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
{
    /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
    /*@dependent@*/ /*@null@*/ xdf_section_data *xsd;
    long pos;
    xdf_reloc *reloc;

    assert(info != NULL);
    xsd = yasm_section_get_data(sect, &xdf_section_data_cb);
    assert(xsd != NULL);

    if (xsd->flags & XDF_SECT_BSS) {
        /* Don't output BSS sections.
         * TODO: Check for non-reserve bytecodes?
         */
        pos = 0;    /* position = 0 because it's not in the file */
        xsd->size = yasm_bc_next_offset(yasm_section_bcs_last(sect));
    } else {
        pos = ftell(info->f);
        if (pos == -1) {
            yasm__fatal(N_("could not get file position on output file"));
            /*@notreached@*/
            return 1;
        }

        info->sect = sect;
        info->xsd = xsd;
        yasm_section_bcs_traverse(sect, info->errwarns, info,
                                  xdf_objfmt_output_bytecode);

        /* Sanity check final section size */
        if (xsd->size != yasm_bc_next_offset(yasm_section_bcs_last(sect)))
            yasm_internal_error(
                N_("xdf: section computed size did not match actual size"));
    }

    /* Empty?  Go on to next section */
    if (xsd->size == 0)
        return 0;

    xsd->scnptr = (unsigned long)pos;

    /* No relocations to output?  Go on to next section */
    if (xsd->nreloc == 0)
        return 0;

    pos = ftell(info->f);
    if (pos == -1) {
        yasm__fatal(N_("could not get file position on output file"));
        /*@notreached@*/
        return 1;
    }
    xsd->relptr = (unsigned long)pos;

    reloc = (xdf_reloc *)yasm_section_relocs_first(sect);
    while (reloc) {
        unsigned char *localbuf = info->buf;
        /*@null@*/ xdf_symrec_data *xsymd;

        xsymd = yasm_symrec_get_data(reloc->reloc.sym, &xdf_symrec_data_cb);
        if (!xsymd)
            yasm_internal_error(
                N_("xdf: no symbol data for relocated symbol"));

        yasm_intnum_get_sized(reloc->reloc.addr, localbuf, 4, 32, 0, 0, 0);
        localbuf += 4;                          /* address of relocation */
        YASM_WRITE_32_L(localbuf, xsymd->index);    /* relocated symbol */
        if (reloc->base) {
            xsymd = yasm_symrec_get_data(reloc->base, &xdf_symrec_data_cb);
            if (!xsymd)
                yasm_internal_error(
                    N_("xdf: no symbol data for relocated base symbol"));
            YASM_WRITE_32_L(localbuf, xsymd->index); /* base symbol */
        } else {
            if (reloc->type == XDF_RELOC_WRT)
                yasm_internal_error(
                    N_("xdf: no base symbol for WRT relocation"));
            YASM_WRITE_32_L(localbuf, 0);           /* no base symbol */
        }
        YASM_WRITE_8(localbuf, reloc->type);        /* type of relocation */
        YASM_WRITE_8(localbuf, reloc->size);        /* size of relocation */
        YASM_WRITE_8(localbuf, reloc->shift);       /* relocation shift */
        YASM_WRITE_8(localbuf, 0);                  /* flags */
        fwrite(info->buf, 16, 1, info->f);

        reloc = (xdf_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc);
    }

    return 0;
}