📄 elf-objfmt.c
字号:
elf_secthead_add_size(shead, sectsize); yasm_intnum_destroy(sectsize); } elf_secthead_set_index(shead, ++info->sindex); return 0; } /* skip empty sections */ if (yasm_section_bcs_last(sect) == yasm_section_bcs_first(sect)) { return 0; } if ((pos = ftell(info->f)) == -1) yasm__error(0, N_("couldn't read position on output stream")); pos = elf_secthead_set_file_offset(shead, pos); if (fseek(info->f, pos, SEEK_SET) < 0) yasm__error(0, N_("couldn't seek on output stream")); info->sect = sect; info->shead = shead; yasm_section_bcs_traverse(sect, info, elf_objfmt_output_bytecode); /* Empty? Go on to next section */ if (elf_secthead_is_empty(shead)) return 0; elf_secthead_set_index(shead, ++info->sindex); /* No relocations to output? Go on to next section */ if (elf_secthead_write_relocs_to_file(info->f, sect, shead) == 0) return 0; elf_secthead_set_rel_index(shead, ++info->sindex); /* name the relocation section .rel[a].foo */ sectname = yasm_section_get_name(sect); relname = elf_secthead_name_reloc_section(sectname); elf_secthead_set_rel_name(shead, elf_strtab_append_str(info->objfmt_elf->shstrtab, relname)); yasm_xfree(relname); return 0;}static intelf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d){ /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d; /*@dependent@*/ /*@null@*/ elf_secthead *shead; /* Don't output absolute sections into the section table */ if (yasm_section_is_absolute(sect)) return 0; if (info == NULL) yasm_internal_error("null info struct"); shead = yasm_section_get_data(sect, &elf_section_data); if (shead == NULL) yasm_internal_error("no section header attached to section"); if(elf_secthead_write_to_file(info->f, shead, info->sindex+1)) info->sindex++; /* output strtab headers here? */ /* relocation entries for .foo are stored in section .rel[a].foo */ if(elf_secthead_write_rel_to_file(info->f, 3, sect, shead, info->sindex+1)) info->sindex++; return 0;}static voidelf_objfmt_output(yasm_objfmt *objfmt, FILE *f, const char *obj_filename, int all_syms, yasm_dbgfmt *df){ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt; elf_objfmt_output_info info; append_local_sym_info localsym_info; long pos; unsigned long elf_shead_addr; elf_secthead *esdn; unsigned long elf_strtab_offset, elf_shstrtab_offset, elf_symtab_offset; unsigned long elf_strtab_size, elf_shstrtab_size, elf_symtab_size; elf_strtab_entry *elf_strtab_name, *elf_shstrtab_name, *elf_symtab_name; unsigned long elf_symtab_nlocal; info.objfmt_elf = objfmt_elf; info.f = f; /* Allocate space for Ehdr by seeking forward */ if (fseek(f, (long)(elf_proghead_get_size()), SEEK_SET) < 0) { yasm__error(0, N_("could not seek on output file")); return; } /* add all (local) syms to symtab because relocation needs a symtab index * if all_syms, register them by name. if not, use strtab entry 0 */ localsym_info.local_names = all_syms; localsym_info.objfmt_elf = objfmt_elf; yasm_symtab_traverse(yasm_object_get_symtab(objfmt_elf->object), &localsym_info, elf_objfmt_append_local_sym); elf_symtab_nlocal = elf_symtab_assign_indices(objfmt_elf->elf_symtab); /* output known sections - includes reloc sections which aren't in yasm's * list. Assign indices as we go. */ info.sindex = 3; if (yasm_object_sections_traverse(objfmt_elf->object, &info, elf_objfmt_output_section)) return; /* add final sections to the shstrtab */ elf_strtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".strtab"); elf_symtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".symtab"); elf_shstrtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".shstrtab"); /* output .shstrtab */ if ((pos = elf_objfmt_output_align(f, 4)) == -1) return; elf_shstrtab_offset = (unsigned long) pos; elf_shstrtab_size = elf_strtab_output_to_file(f, objfmt_elf->shstrtab); /* output .strtab */ if ((pos = elf_objfmt_output_align(f, 4)) == -1) return; elf_strtab_offset = (unsigned long) pos; elf_strtab_size = elf_strtab_output_to_file(f, objfmt_elf->strtab); /* output .symtab - last section so all others have indexes */ if ((pos = elf_objfmt_output_align(f, 4)) == -1) return; elf_symtab_offset = (unsigned long) pos; elf_symtab_size = elf_symtab_write_to_file(f, objfmt_elf->elf_symtab); /* output section header table */ if ((pos = elf_objfmt_output_align(f, 16)) == -1) return; elf_shead_addr = (unsigned long) pos; /* stabs debugging support */ if (strcmp(yasm_dbgfmt_keyword(df), "stabs")==0) { yasm_section *stabsect = yasm_object_find_general(objfmt_elf->object, ".stab"); yasm_section *stabstrsect = yasm_object_find_general(objfmt_elf->object, ".stabstr"); if (stabsect && stabstrsect) { elf_secthead *stab = yasm_section_get_data(stabsect, &elf_section_data); elf_secthead *stabstr = yasm_section_get_data(stabstrsect, &elf_section_data); if (stab && stabstr) { elf_secthead_set_link(stab, elf_secthead_get_index(stabstr)); } else yasm_internal_error(N_("missing .stab or .stabstr section/data")); } } /* output dummy section header - 0 */ info.sindex = 0; esdn = elf_secthead_create(NULL, SHT_NULL, 0, 0, 0, 0); elf_secthead_write_to_file(f, esdn, 0); elf_secthead_destroy(esdn); esdn = elf_secthead_create(elf_shstrtab_name, SHT_STRTAB, 0, 1, elf_shstrtab_offset, elf_shstrtab_size); elf_secthead_write_to_file(f, esdn, 1); elf_secthead_destroy(esdn); esdn = elf_secthead_create(elf_strtab_name, SHT_STRTAB, 0, 2, elf_strtab_offset, elf_strtab_size); elf_secthead_write_to_file(f, esdn, 2); elf_secthead_destroy(esdn); esdn = elf_secthead_create(elf_symtab_name, SHT_SYMTAB, 0, 3, elf_symtab_offset, elf_symtab_size); elf_secthead_set_info(esdn, elf_symtab_nlocal); elf_secthead_set_link(esdn, 2); /* for .strtab, which is index 2 */ elf_secthead_write_to_file(f, esdn, 3); elf_secthead_destroy(esdn); info.sindex = 3; /* output remaining section headers */ yasm_object_sections_traverse(objfmt_elf->object, &info, elf_objfmt_output_secthead); /* output Ehdr */ if (fseek(f, 0, SEEK_SET) < 0) { yasm__error(0, N_("could not seek on output file")); return; } elf_proghead_write_to_file(f, elf_shead_addr, info.sindex+1, 1);}static voidelf_objfmt_destroy(yasm_objfmt *objfmt){ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt; elf_symtab_destroy(objfmt_elf->elf_symtab); elf_strtab_destroy(objfmt_elf->shstrtab); elf_strtab_destroy(objfmt_elf->strtab); yasm_xfree(objfmt);}static /*@observer@*/ /*@null@*/ yasm_section *elf_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams, /*@unused@*/ /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line){ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt; yasm_valparam *vp = yasm_vps_first(valparams); yasm_section *retval; int isnew; unsigned long type = SHT_PROGBITS; unsigned long flags = SHF_ALLOC; unsigned long align = 4; yasm_intnum *align_intn = NULL; int flags_override = 0; char *sectname; int resonly = 0; static const struct { const char *name; unsigned long flags; } flagquals[] = { { "alloc", SHF_ALLOC }, { "exec", SHF_EXECINSTR }, { "write", SHF_WRITE }, /*{ "progbits", SHT_PROGBITS },*/ /*{ "align", 0 } */ }; if (!vp || vp->param || !vp->val) return NULL; sectname = vp->val; if (strcmp(sectname, ".bss") == 0) { type = SHT_NOBITS; flags = SHF_ALLOC + SHF_WRITE; resonly = 1; } else if (strcmp(sectname, ".data") == 0) { type = SHT_PROGBITS; flags = SHF_ALLOC + SHF_WRITE; } else if (strcmp(sectname, ".rodata") == 0) { type = SHT_PROGBITS; flags = SHF_ALLOC; } else if (strcmp(sectname, ".text") == 0) { align = 16; type = SHT_PROGBITS; flags = SHF_ALLOC + SHF_EXECINSTR; } else { /* Default to code */ align = 1; } while ((vp = yasm_vps_next(vp))) { size_t i; int match; match = 0; for (i=0; i<NELEMS(flagquals) && !match; i++) { if (yasm__strcasecmp(vp->val, flagquals[i].name) == 0) { flags_override = 1; match = 1; flags |= flagquals[i].flags; } else if (yasm__strcasecmp(vp->val+2, flagquals[i].name) == 0 && yasm__strncasecmp(vp->val, "no", 2) == 0) { flags &= ~flagquals[i].flags; flags_override = 1; match = 1; } } if (match) ; else if (yasm__strcasecmp(vp->val, "progbits") == 0) { type |= SHT_PROGBITS; } else if (yasm__strcasecmp(vp->val, "noprogbits") == 0) { type &= ~SHT_PROGBITS; } else if (yasm__strcasecmp(vp->val, "align") == 0 && vp->param) { /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr; unsigned long addralign; align_expr = yasm_expr_get_intnum(&vp->param, NULL); if (!align_expr) { yasm__error(line, N_("argument to `%s' is not a power of two"), vp->val); return NULL; } addralign = yasm_intnum_get_uint(align_expr); /* Alignments must be a power of two. */ if ((addralign & (addralign - 1)) != 0) { yasm__error(line, N_("argument to `%s' is not a power of two"), vp->val); return NULL; } align_intn = yasm_intnum_copy(align_expr); } else yasm__warning(YASM_WARN_GENERAL, line, N_("Unrecognized qualifier `%s'"), vp->val); } retval = yasm_object_get_general(objfmt_elf->object, sectname, 0, resonly, &isnew, line); if (isnew) { elf_secthead *esd; yasm_symrec *sym; elf_strtab_entry *name = elf_strtab_append_str(objfmt_elf->shstrtab, sectname); esd = elf_secthead_create(name, type, flags, objfmt_elf->parse_scnum++, 0, 0); if (!align_intn) align_intn = yasm_intnum_create_uint(align); if (align_intn) elf_secthead_set_align(esd, align_intn); yasm_section_add_data(retval, &elf_section_data, esd); sym = yasm_symtab_define_label( yasm_object_get_symtab(objfmt_elf->object), sectname, yasm_section_bcs_first(retval), 1, line); elf_secthead_set_sym(esd, sym); } else if (flags_override) yasm__warning(YASM_WARN_GENERAL, line, N_("section flags ignored on section redeclaration")); return retval;}static yasm_symrec *elf_objfmt_extern_declare(yasm_objfmt *objfmt, const char *name, /*@unused@*/ /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line){ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt; yasm_symrec *sym; sym = yasm_symtab_declare(objfmt_elf->symtab, name, YASM_SYM_EXTERN, line); elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL, STT_NOTYPE, NULL, 0); return sym;}static yasm_symrec *elf_objfmt_global_declare(yasm_objfmt *objfmt, const char *name, /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line){ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt; yasm_symrec *sym; elf_symbol_type type = STT_NOTYPE; yasm_expr *size = NULL; sym = yasm_symtab_declare(objfmt_elf->symtab, name, YASM_SYM_GLOBAL, line); if (objext_valparams) { yasm_valparam *vp = yasm_vps_first(objext_valparams); if (vp && vp->val) { if (yasm__strcasecmp(vp->val, "function") == 0) type = STT_FUNC; else if (yasm__strcasecmp(vp->val, "data") == 0 || yasm__strcasecmp(vp->val, "object") == 0) type = STT_OBJECT; else yasm__error(line, N_("unrecognized symbol type `%s'"), vp->val); vp = yasm_vps_next(vp); } if (vp && !vp->val && vp->param) { size = vp->param; vp->param = NULL; /* to avoid deleting the expr */ } } elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL, type, size, 0); return sym;}static yasm_symrec *elf_objfmt_common_declare(yasm_objfmt *objfmt, const char *name, /*@only@*/ yasm_expr *size, /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line){ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt; yasm_symrec *sym; unsigned long addralign = 0; sym = yasm_symtab_declare(objfmt_elf->symtab, name, YASM_SYM_COMMON, line); if (objext_valparams) { yasm_valparam *vp = yasm_vps_first(objext_valparams); if (vp && !vp->val && vp->param) { /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr; align_expr = yasm_expr_get_intnum(&vp->param, NULL); if (!align_expr) { yasm__error(line, N_("alignment constraint is not a power of two")); return sym; } addralign = yasm_intnum_get_uint(align_expr); /* Alignments must be a power of two. */ if ((addralign & (addralign - 1)) != 0) { yasm__error(line, N_("alignment constraint is not a power of two")); return sym; } } else if (vp && vp->val) yasm__warning(YASM_WARN_GENERAL, line, N_("Unrecognized qualifier `%s'"), vp->val); } elf_objfmt_symtab_append(objfmt_elf, sym, SHN_COMMON, STB_GLOBAL, STT_NOTYPE, size, addralign); return sym;}static intelf_objfmt_directive(/*@unused@*/ yasm_objfmt *objfmt, /*@unused@*/ const char *name, /*@unused@*/ yasm_valparamhead *valparams, /*@unused@*/ /*@null@*/ yasm_valparamhead *objext_valparams, /*@unused@*/ unsigned long line){ return 1; /* no objfmt directives */}/* Define valid debug formats to use with this object format */static const char *elf_objfmt_dbgfmt_keywords[] = { "null", "stabs", NULL};/* Define objfmt structure -- see objfmt.h for details */yasm_objfmt_module yasm_elf_LTX_objfmt = { YASM_OBJFMT_VERSION, "ELF", "elf", "o", ".text", 32, elf_objfmt_dbgfmt_keywords, "null", elf_objfmt_create, elf_objfmt_output, elf_objfmt_destroy, elf_objfmt_section_switch, elf_objfmt_extern_declare, elf_objfmt_global_declare, elf_objfmt_common_declare, elf_objfmt_directive};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -