static elf_symtab_entry *
elf_objfmt_symtab_append(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym,
                         elf_section_index sectidx, elf_symbol_binding bind,
                         elf_symbol_type type, elf_symbol_vis vis,
                         yasm_expr *size, elf_address *value,
                         yasm_object *object)
{
    elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);

    if (!entry) {
        /*@only@*/ char *symname = yasm_symrec_get_global_name(sym, object);
        elf_strtab_entry *name =
            elf_strtab_append_str(objfmt_elf->strtab, symname);
        yasm_xfree(symname);
        entry = elf_symtab_entry_create(name, sym);
        yasm_symrec_add_data(sym, &elf_symrec_data, entry);
    }

    /* Only append to table if not already appended */
    if (!elf_sym_in_table(entry))
        elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);

    elf_symtab_set_nonzero(entry, NULL, sectidx, bind, type, size, value);
    elf_sym_set_visibility(entry, vis);

    return entry;
}
示例#2
0
static unsigned int
elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc)
{
    if (reloc->wrt) {
        const elf_machine_ssym *ssym = (elf_machine_ssym *)
            yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
        if (!ssym || reloc->valsize != ssym->size)
            yasm_internal_error(N_("Unsupported WRT"));

        /* Force TLS type; this is required by the linker. */
        if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
            elf_symtab_entry *esym;

            esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
            if (esym)
                esym->type = STT_TLS;
        }
        /* Map PC-relative GOT to appropriate relocation */
        if (reloc->rtype_rel && ssym->reloc == R_X86_64_GOT32)
            return (unsigned char) R_X86_64_GOTPCREL;
        return (unsigned char) ssym->reloc;
    } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
        return (unsigned char) R_X86_64_GOTPC32;
    } else if (reloc->is_GOT_sym && reloc->valsize == 64) {
        return (unsigned char) R_X86_64_GOTPC64;
    } else if (reloc->rtype_rel) {
        switch (reloc->valsize) {
            case 8: return (unsigned char) R_X86_64_PC8;
            case 16: return (unsigned char) R_X86_64_PC16;
            case 32: return (unsigned char) R_X86_64_PC32;
            case 64: return (unsigned char) R_X86_64_PC64;
            default: yasm_internal_error(N_("Unsupported relocation size"));
        }
    } else {
        switch (reloc->valsize) {
            case 8: return (unsigned char) R_X86_64_8;
            case 16: return (unsigned char) R_X86_64_16;
            case 32: return (unsigned char) R_X86_64_32;
            case 64: return (unsigned char) R_X86_64_64;
            default: yasm_internal_error(N_("Unsupported relocation size"));
        }
    }
    return 0;
}
示例#3
0
static int
elf_x86_amd64_accepts_reloc(size_t val, yasm_symrec *wrt)
{
    if (wrt) {
        const elf_machine_ssym *ssym = (elf_machine_ssym *)
            yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
        if (!ssym || val != ssym->size)
            return 0;
        return 1;
    }
    return (val&(val-1)) ? 0 : ((val & (8|16|32|64)) != 0);
}
示例#4
0
static int
xdf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
{
    /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
    yasm_objfmt_xdf *objfmt_xdf;
    /*@dependent@*/ /*@null@*/ xdf_section_data *xsd;
    /*@null@*/ xdf_symrec_data *xsymd;
    unsigned char *localbuf;

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

    localbuf = info->buf;
    xsymd = yasm_symrec_get_data(xsd->sym, &xdf_symrec_data_cb);
    assert(xsymd != NULL);

    YASM_WRITE_32_L(localbuf, xsymd->index);    /* section name symbol */
    if (xsd->addr) {
        yasm_intnum_get_sized(xsd->addr, localbuf, 8, 64, 0, 0, 0);
        localbuf += 8;                          /* physical address */
    } else {
        YASM_WRITE_32_L(localbuf, 0);
        YASM_WRITE_32_L(localbuf, 0);
    }
    if (xsd->vaddr) {
        yasm_intnum_get_sized(xsd->vaddr, localbuf, 8, 64, 0, 0, 0);
        localbuf += 8;                          /* virtual address */
    } else if (xsd->addr) {
        yasm_intnum_get_sized(xsd->addr, localbuf, 8, 64, 0, 0, 0);
        localbuf += 8;                          /* VA=PA */
    } else {
        YASM_WRITE_32_L(localbuf, 0);
        YASM_WRITE_32_L(localbuf, 0);
    }
    YASM_WRITE_16_L(localbuf, yasm_section_get_align(sect)); /* alignment */
    YASM_WRITE_16_L(localbuf, xsd->flags);      /* flags */
    YASM_WRITE_32_L(localbuf, xsd->scnptr);     /* file ptr to data */
    YASM_WRITE_32_L(localbuf, xsd->size);       /* section size */
    YASM_WRITE_32_L(localbuf, xsd->relptr);     /* file ptr to relocs */
    YASM_WRITE_32_L(localbuf, xsd->nreloc); /* num of relocation entries */
    fwrite(info->buf, 40, 1, info->f);

    return 0;
}
示例#5
0
static unsigned int
elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc,
                                     yasm_symrec **ssyms)
{
    if (reloc->wrt) {
        size_t i;
        for (i=0; i<NELEMS(elf_x86_amd64_ssyms); i++) {
            if (reloc->wrt == ssyms[i] &&
                reloc->valsize == elf_x86_amd64_ssyms[i].size) {
                /* Force TLS type; this is required by the linker. */
                if (elf_x86_amd64_ssyms[i].sym_rel & ELF_SSYM_THREAD_LOCAL) {
                    elf_symtab_entry *esym;

                    esym = yasm_symrec_get_data(reloc->reloc.sym,
                                                &elf_symrec_data);
                    if (esym)
                        esym->type = STT_TLS;
                }
                /* Map PC-relative GOT to appropriate relocation */
                if (reloc->rtype_rel &&
                    elf_x86_amd64_ssyms[i].reloc == R_X86_64_GOT32)
                    return (unsigned char) R_X86_64_GOTPCREL;
                return (unsigned char) elf_x86_amd64_ssyms[i].reloc;
            }
        }
        yasm_internal_error(N_("Unsupported WRT"));
    } else if (reloc->rtype_rel) {
        switch (reloc->valsize) {
            case 8: return (unsigned char) R_X86_64_PC8;
            case 16: return (unsigned char) R_X86_64_PC16;
            case 32: return (unsigned char) R_X86_64_PC32;
            default: yasm_internal_error(N_("Unsupported relocation size"));
        }
    } else {
        switch (reloc->valsize) {
            case 8: return (unsigned char) R_X86_64_8;
            case 16: return (unsigned char) R_X86_64_16;
            case 32: return (unsigned char) R_X86_64_32;
            case 64: return (unsigned char) R_X86_64_64;
            default: yasm_internal_error(N_("Unsupported relocation size"));
        }
    }
    return 0;
}
示例#6
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;
}