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; }
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; }
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); }
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; }
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; }
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; }