static void elf_x86_amd64_write_proghead(unsigned char **bufpp, elf_offset secthead_addr, unsigned long secthead_count, elf_section_index shstrtab_index) { unsigned char *bufp = *bufpp; unsigned char *buf = bufp-4; YASM_WRITE_8(bufp, ELFCLASS64); /* elf class */ YASM_WRITE_8(bufp, ELFDATA2LSB); /* data encoding :: MSB? */ YASM_WRITE_8(bufp, EV_CURRENT); /* elf version */ YASM_WRITE_8(bufp, ELFOSABI_SYSV); /* os/abi */ YASM_WRITE_8(bufp, 0); /* SYSV v3 ABI=0 */ while (bufp-buf < EI_NIDENT) /* e_ident padding */ YASM_WRITE_8(bufp, 0); YASM_WRITE_16_L(bufp, ET_REL); /* e_type - object file */ YASM_WRITE_16_L(bufp, EM_X86_64); /* e_machine - or others */ YASM_WRITE_32_L(bufp, EV_CURRENT); /* elf version */ YASM_WRITE_64Z_L(bufp, 0); /* e_entry */ YASM_WRITE_64Z_L(bufp, 0); /* e_phoff */ YASM_WRITE_64Z_L(bufp, secthead_addr); /* e_shoff secthead off */ YASM_WRITE_32_L(bufp, 0); /* e_flags */ YASM_WRITE_16_L(bufp, EHDR64_SIZE); /* e_ehsize */ YASM_WRITE_16_L(bufp, 0); /* e_phentsize */ YASM_WRITE_16_L(bufp, 0); /* e_phnum */ YASM_WRITE_16_L(bufp, SHDR64_SIZE); /* e_shentsize */ YASM_WRITE_16_L(bufp, secthead_count); /* e_shnum */ YASM_WRITE_16_L(bufp, shstrtab_index); /* e_shstrndx */ *bufpp = bufp; }
static void elf_x86_amd64_write_secthead_rel(unsigned char *bufp, elf_secthead *shead, elf_section_index symtab_idx, elf_section_index sindex) { yasm_intnum *nreloc; yasm_intnum *relocsize; YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0); YASM_WRITE_32_L(bufp, SHT_RELA); YASM_WRITE_64Z_L(bufp, 0); YASM_WRITE_64Z_L(bufp, 0); YASM_WRITE_64Z_L(bufp, shead->rel_offset); nreloc = yasm_intnum_create_uint(shead->nreloc); relocsize = yasm_intnum_create_uint(RELOC64A_SIZE); yasm_intnum_calc(relocsize, YASM_EXPR_MUL, nreloc); YASM_WRITE_64I_L(bufp, relocsize); /* size */ yasm_intnum_destroy(nreloc); yasm_intnum_destroy(relocsize); YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */ YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */ YASM_WRITE_64Z_L(bufp, RELOC64_ALIGN); /* align */ YASM_WRITE_64Z_L(bufp, RELOC64A_SIZE); /* entity size */ }
static void elf_x86_x86_write_proghead(unsigned char **bufpp, elf_offset secthead_addr, unsigned long secthead_count, elf_section_index shstrtab_index) { unsigned char *bufp = *bufpp; unsigned char *buf = bufp-4; YASM_WRITE_8(bufp, ELFCLASS32); /* elf class */ YASM_WRITE_8(bufp, ELFDATA2LSB); /* data encoding :: MSB? */ YASM_WRITE_8(bufp, EV_CURRENT); /* elf version */ while (bufp-buf < EI_NIDENT) /* e_ident padding */ YASM_WRITE_8(bufp, 0); YASM_WRITE_16_L(bufp, ET_REL); /* e_type - object file */ YASM_WRITE_16_L(bufp, EM_386); /* e_machine - or others */ YASM_WRITE_32_L(bufp, EV_CURRENT); /* elf version */ YASM_WRITE_32_L(bufp, 0); /* e_entry exection startaddr */ YASM_WRITE_32_L(bufp, 0); /* e_phoff program header off */ YASM_WRITE_32_L(bufp, secthead_addr); /* e_shoff section header off */ YASM_WRITE_32_L(bufp, 0); /* e_flags also by arch */ YASM_WRITE_16_L(bufp, EHDR32_SIZE); /* e_ehsize */ YASM_WRITE_16_L(bufp, 0); /* e_phentsize */ YASM_WRITE_16_L(bufp, 0); /* e_phnum */ YASM_WRITE_16_L(bufp, SHDR32_SIZE); /* e_shentsize */ YASM_WRITE_16_L(bufp, secthead_count); /* e_shnum */ YASM_WRITE_16_L(bufp, shstrtab_index); /* e_shstrndx */ *bufpp = bufp; }
static void elf_x86_amd64_write_reloc(unsigned char *bufp, elf_reloc_entry *reloc, unsigned int r_type, unsigned int r_sym) { YASM_WRITE_64I_L(bufp, reloc->reloc.addr); /*YASM_WRITE_64_L(bufp, ELF64_R_INFO(r_sym, r_type));*/ YASM_WRITE_64C_L(bufp, r_sym, r_type); if (reloc->addend) YASM_WRITE_64I_L(bufp, reloc->addend); else { YASM_WRITE_32_L(bufp, 0); YASM_WRITE_32_L(bufp, 0); } }
static void elf_x86_amd64_write_secthead(unsigned char *bufp, elf_secthead *shead) { YASM_WRITE_32_L(bufp, shead->name ? shead->name->index : 0); YASM_WRITE_32_L(bufp, shead->type); YASM_WRITE_64Z_L(bufp, shead->flags); YASM_WRITE_64Z_L(bufp, 0); /* vmem address */ YASM_WRITE_64Z_L(bufp, shead->offset); YASM_WRITE_64I_L(bufp, shead->size); YASM_WRITE_32_L(bufp, shead->link); YASM_WRITE_32_L(bufp, shead->info); YASM_WRITE_64Z_L(bufp, shead->align); YASM_WRITE_64Z_L(bufp, shead->entsize); }
static void elf_x86_x86_write_reloc(unsigned char *bufp, elf_reloc_entry *reloc, unsigned int r_type, unsigned int r_sym) { YASM_WRITE_32I_L(bufp, reloc->reloc.addr); YASM_WRITE_32_L(bufp, ELF32_R_INFO((unsigned long)r_sym, (unsigned char)r_type)); }
static void elf_x86_x86_write_secthead_rel(unsigned char *bufp, elf_secthead *shead, elf_section_index symtab_idx, elf_section_index sindex) { YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0); YASM_WRITE_32_L(bufp, SHT_REL); YASM_WRITE_32_L(bufp, 0); YASM_WRITE_32_L(bufp, 0); YASM_WRITE_32_L(bufp, shead->rel_offset); YASM_WRITE_32_L(bufp, RELOC32_SIZE * shead->nreloc);/* size */ YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */ YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */ YASM_WRITE_32_L(bufp, RELOC32_ALIGN); /* align */ YASM_WRITE_32_L(bufp, RELOC32_SIZE); /* entity size */ }
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 void elf_x86_amd64_write_symtab_entry(unsigned char *bufp, elf_symtab_entry *entry, yasm_intnum *value_intn, yasm_intnum *size_intn) { YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0); YASM_WRITE_8(bufp, ELF64_ST_INFO(entry->bind, entry->type)); YASM_WRITE_8(bufp, ELF64_ST_OTHER(entry->vis)); if (entry->sect) { elf_secthead *shead = yasm_section_get_data(entry->sect, &elf_section_data); if (!shead) yasm_internal_error(N_("symbol references section without data")); YASM_WRITE_16_L(bufp, shead->index); } else { YASM_WRITE_16_L(bufp, entry->index); } YASM_WRITE_64I_L(bufp, value_intn); YASM_WRITE_64I_L(bufp, size_intn); }
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); }
static int xdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d) { /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d; yasm_sym_vis vis = yasm_symrec_get_visibility(sym); assert(info != NULL); if (info->all_syms || vis != YASM_SYM_LOCAL) { /*@only@*/ char *name = yasm_symrec_get_global_name(sym, info->object); const yasm_expr *equ_val; const yasm_intnum *intn; size_t len = strlen(name); unsigned long value = 0; long scnum = -3; /* -3 = debugging symbol */ /*@dependent@*/ /*@null@*/ yasm_section *sect; /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc; unsigned long flags = 0; unsigned char *localbuf; if (vis & YASM_SYM_GLOBAL) flags = XDF_SYM_GLOBAL; /* Look at symrec for value/scnum/etc. */ if (yasm_symrec_get_label(sym, &precbc)) { if (precbc) sect = yasm_bc_get_section(precbc); else sect = NULL; /* it's a label: get value and offset. * If there is not a section, leave as debugging symbol. */ if (sect) { /*@dependent@*/ /*@null@*/ xdf_section_data *csectd; csectd = yasm_section_get_data(sect, &xdf_section_data_cb); if (csectd) scnum = csectd->scnum; else yasm_internal_error(N_("didn't understand section")); if (precbc) value += yasm_bc_next_offset(precbc); } } else if ((equ_val = yasm_symrec_get_equ(sym))) { yasm_expr *equ_val_copy = yasm_expr_copy(equ_val); intn = yasm_expr_get_intnum(&equ_val_copy, 1); if (!intn) { if (vis & YASM_SYM_GLOBAL) { yasm_error_set(YASM_ERROR_NOT_CONSTANT, N_("global EQU value not an integer expression")); yasm_errwarn_propagate(info->errwarns, equ_val->line); } } else value = yasm_intnum_get_uint(intn); yasm_expr_destroy(equ_val_copy); flags |= XDF_SYM_EQU; scnum = -2; /* -2 = absolute symbol */ } else { if (vis & YASM_SYM_EXTERN) { flags = XDF_SYM_EXTERN; scnum = -1; } } localbuf = info->buf; YASM_WRITE_32_L(localbuf, scnum); /* section number */ YASM_WRITE_32_L(localbuf, value); /* value */ YASM_WRITE_32_L(localbuf, info->strtab_offset); info->strtab_offset += (unsigned long)(len+1); YASM_WRITE_32_L(localbuf, flags); /* flags */ fwrite(info->buf, 16, 1, info->f); yasm_xfree(name); } 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; }