📄 outaout.c
字号:
if (exact) { /* * Find a symbol pointing _exactly_ at this one. */ for (sym = shead; sym; sym = sym->next) if (sym->value == offset) break; } else { /* * Find the nearest symbol below this one. */ sym = NULL; for (sm = shead; sm; sm = sm->next) if (sm->value <= offset && (!sym || sm->value > sym->value)) sym = sm; } if (!sym && exact) { error (ERR_NONFATAL, "unable to find a suitable global symbol" " for this reference"); return 0; } r = *sect->tail = nasm_malloc(sizeof(struct Reloc)); sect->tail = &r->next; r->next = NULL; r->address = sect->len; r->symbol = sym->symnum; r->reltype = type | RELTYPE_SYMFLAG; r->bytes = bytes; sect->nrelocs++; return offset - sym->value;}/* * This routine deals with ..gotoff relocations. These _must_ refer * to a symbol, due to a perversity of *BSD's PIC implementation, * and it must be a non-global one as well; so we store `asym', the * first nonglobal symbol defined in each section, and always work * from that. Relocation type is always RELTYPE_GOTOFF. * * Return value is the adjusted value of `addr', having become an * offset from the `asym' symbol rather than the section. */static long aout_add_gotoff_reloc (struct Section *sect, long segment, long offset, int bytes) { struct Reloc *r; struct Symbol *asym; /* * First look up the segment to find whether it's text, data, * bss or an external symbol. */ asym = NULL; if (segment == stext.index) asym = stext.asym; else if (segment == sdata.index) asym = sdata.asym; else if (segment == sbss.index) asym = sbss.asym; if (!asym) error (ERR_NONFATAL, "`..gotoff' relocations require a non-global" " symbol in the section"); r = *sect->tail = nasm_malloc(sizeof(struct Reloc)); sect->tail = &r->next; r->next = NULL; r->address = sect->len; r->symbol = asym->symnum; r->reltype = RELTYPE_GOTOFF; r->bytes = bytes; sect->nrelocs++; return offset - asym->value;}static void aout_out (long segto, const void *data, unsigned long type, long segment, long wrt) { struct Section *s; long realbytes = type & OUT_SIZMASK; long addr; unsigned char mydata[4], *p; type &= OUT_TYPMASK; /* * handle absolute-assembly (structure definitions) */ if (segto == NO_SEG) { if (type != OUT_RESERVE) error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]" " space"); return; } if (segto == stext.index) s = &stext; else if (segto == sdata.index) s = &sdata; else if (segto == sbss.index) s = NULL; else { error(ERR_WARNING, "attempt to assemble code in" " segment %d: defaulting to `.text'", segto); s = &stext; } if (!s && type != OUT_RESERVE) { error(ERR_WARNING, "attempt to initialise memory in the" " BSS section: ignored"); if (type == OUT_REL2ADR) realbytes = 2; else if (type == OUT_REL4ADR) realbytes = 4; sbss.len += realbytes; return; } if (type == OUT_RESERVE) { if (s) { error(ERR_WARNING, "uninitialised space declared in" " %s section: zeroing", (segto == stext.index ? "code" : "data")); aout_sect_write (s, NULL, realbytes); } else sbss.len += realbytes; } else if (type == OUT_RAWDATA) { if (segment != NO_SEG) error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG"); aout_sect_write (s, data, realbytes); } else if (type == OUT_ADDRESS) { addr = *(long *)data; if (segment != NO_SEG) { if (segment % 2) { error(ERR_NONFATAL, "a.out format does not support" " segment base references"); } else { if (wrt == NO_SEG) { aout_add_reloc (s, segment, RELTYPE_ABSOLUTE, realbytes); } else if (!bsd) { error (ERR_NONFATAL, "Linux a.out format does not support" " any use of WRT"); wrt = NO_SEG; /* we can at least _try_ to continue */ } else if (wrt == aout_gotpc_sect+1) { is_pic = 0x40; aout_add_reloc (s, segment, RELTYPE_GOTPC, realbytes); } else if (wrt == aout_gotoff_sect+1) { is_pic = 0x40; addr = aout_add_gotoff_reloc (s, segment, addr, realbytes); } else if (wrt == aout_got_sect+1) { is_pic = 0x40; addr = aout_add_gsym_reloc (s, segment, addr, RELTYPE_GOT, realbytes, TRUE); } else if (wrt == aout_sym_sect+1) { addr = aout_add_gsym_reloc (s, segment, addr, RELTYPE_ABSOLUTE, realbytes, FALSE); } else if (wrt == aout_plt_sect+1) { is_pic = 0x40; error(ERR_NONFATAL, "a.out format cannot produce non-PC-" "relative PLT references"); } else { error (ERR_NONFATAL, "a.out format does not support this" " use of WRT"); wrt = NO_SEG; /* we can at least _try_ to continue */ } } } p = mydata; if (realbytes == 2) WRITESHORT (p, addr); else WRITELONG (p, addr); aout_sect_write (s, mydata, realbytes); } else if (type == OUT_REL2ADR) { if (segment == segto) error(ERR_PANIC, "intra-segment OUT_REL2ADR"); if (segment != NO_SEG && segment % 2) { error(ERR_NONFATAL, "a.out format does not support" " segment base references"); } else { if (wrt == NO_SEG) { aout_add_reloc (s, segment, RELTYPE_RELATIVE, 2); } else if (!bsd) { error (ERR_NONFATAL, "Linux a.out format does not support" " any use of WRT"); wrt = NO_SEG; /* we can at least _try_ to continue */ } else if (wrt == aout_plt_sect+1) { is_pic = 0x40; aout_add_reloc (s, segment, RELTYPE_PLT, 2); } else if (wrt == aout_gotpc_sect+1 || wrt == aout_gotoff_sect+1 || wrt == aout_got_sect+1) { error(ERR_NONFATAL, "a.out format cannot produce PC-" "relative GOT references"); } else { error (ERR_NONFATAL, "a.out format does not support this" " use of WRT"); wrt = NO_SEG; /* we can at least _try_ to continue */ } } p = mydata; WRITESHORT (p, *(long*)data-(realbytes + s->len)); aout_sect_write (s, mydata, 2L); } else if (type == OUT_REL4ADR) { if (segment == segto) error(ERR_PANIC, "intra-segment OUT_REL4ADR"); if (segment != NO_SEG && segment % 2) { error(ERR_NONFATAL, "a.out format does not support" " segment base references"); } else { if (wrt == NO_SEG) { aout_add_reloc (s, segment, RELTYPE_RELATIVE, 4); } else if (!bsd) { error (ERR_NONFATAL, "Linux a.out format does not support" " any use of WRT"); wrt = NO_SEG; /* we can at least _try_ to continue */ } else if (wrt == aout_plt_sect+1) { is_pic = 0x40; aout_add_reloc (s, segment, RELTYPE_PLT, 4); } else if (wrt == aout_gotpc_sect+1 || wrt == aout_gotoff_sect+1 || wrt == aout_got_sect+1) { error(ERR_NONFATAL, "a.out format cannot produce PC-" "relative GOT references"); } else { error (ERR_NONFATAL, "a.out format does not support this" " use of WRT"); wrt = NO_SEG; /* we can at least _try_ to continue */ } } p = mydata; WRITELONG (p, *(long*)data-(realbytes + s->len)); aout_sect_write (s, mydata, 4L); }}static void aout_pad_sections(void) { static unsigned char pad[] = { 0x90, 0x90, 0x90, 0x90 }; /* * Pad each of the text and data sections with NOPs until their * length is a multiple of four. (NOP == 0x90.) Also increase * the length of the BSS section similarly. */ aout_sect_write (&stext, pad, (-(long)stext.len) & 3); aout_sect_write (&sdata, pad, (-(long)sdata.len) & 3); sbss.len = (sbss.len + 3) & ~3;}/* * a.out files have the curious property that all references to * things in the data or bss sections are done by addresses which * are actually relative to the start of the _text_ section, in the * _file_. (No relation to what happens after linking. No idea why * this should be so. It's very strange.) So we have to go through * the relocation table, _after_ the final size of each section is * known, and fix up the relocations pointed to. */static void aout_fixup_relocs(struct Section *sect) { struct Reloc *r; saa_rewind (sect->data); for (r = sect->head; r; r = r->next) { unsigned char *p, *q, blk[4]; long l; saa_fread (sect->data, r->address, blk, (long)r->bytes); p = q = blk; l = *p++; if (r->bytes > 1) { l += ((long)*p++) << 8; if (r->bytes == 4) { l += ((long)*p++) << 16; l += ((long)*p++) << 24; } } if (r->symbol == -SECT_DATA) l += stext.len; else if (r->symbol == -SECT_BSS) l += stext.len + sdata.len; if (r->bytes == 4) WRITELONG(q, l); else if (r->bytes == 2) WRITESHORT(q, l); else *q++ = l & 0xFF; saa_fwrite (sect->data, r->address, blk, (long)r->bytes); }}static void aout_write(void) { /* * Emit the a.out header. */ /* OMAGIC, M_386 or MID_I386, no flags */ fwritelong (bsd ? 0x07018600 | is_pic : 0x640107L, aoutfp); fwritelong (stext.len, aoutfp); fwritelong (sdata.len, aoutfp); fwritelong (sbss.len, aoutfp); fwritelong (nsyms * 12, aoutfp); /* length of symbol table */ fwritelong (0L, aoutfp); /* object files have no entry point */ fwritelong (stext.nrelocs * 8, aoutfp); /* size of text relocs */ fwritelong (sdata.nrelocs * 8, aoutfp); /* size of data relocs */ /* * Write out the code section and the data section. */ saa_fpwrite (stext.data, aoutfp); saa_fpwrite (sdata.data, aoutfp); /* * Write out the relocations. */ aout_write_relocs (stext.head); aout_write_relocs (sdata.head); /* * Write the symbol table. */ aout_write_syms (); /* * And the string table. */ fwritelong (strslen+4, aoutfp); /* length includes length count */ saa_fpwrite (strs, aoutfp);}static void aout_write_relocs (struct Reloc *r) { while (r) { unsigned long word2; fwritelong (r->address, aoutfp); if (r->symbol >= 0) word2 = r->symbol; else word2 = -r->symbol; word2 |= r->reltype << 24; word2 |= (r->bytes == 1 ? 0 : r->bytes == 2 ? 0x2000000L : 0x4000000L); fwritelong (word2, aoutfp); r = r->next; }}static void aout_write_syms (void) { unsigned long i; saa_rewind (syms); for (i = 0; i < nsyms; i++) { struct Symbol *sym = saa_rstruct(syms); fwritelong (sym->strpos, aoutfp); fwritelong ((long)sym->type & ~SYM_WITH_SIZE, aoutfp); /* * Fix up the symbol value now we know the final section * sizes. */ if ((sym->type & SECT_MASK) == SECT_DATA) sym->value += stext.len; if ((sym->type & SECT_MASK) == SECT_BSS) sym->value += stext.len + sdata.len; fwritelong (sym->value, aoutfp); /* * Output a size record if necessary. */ if (sym->type & SYM_WITH_SIZE) { fwritelong(sym->strpos, aoutfp); fwritelong(0x0DL, aoutfp); /* special value: means size */ fwritelong(sym->size, aoutfp); i++; /* use up another of `nsyms' */ } }}static void aout_sect_write (struct Section *sect, const unsigned char *data, unsigned long len) { saa_wbytes (sect->data, data, len); sect->len += len;}static long aout_segbase (long segment) { return segment;}static int aout_directive (char *directive, char *value, int pass) { return 0;}static void aout_filename (char *inname, char *outname, efunc error) { standard_extension (inname, outname, ".o", error);}static const char *aout_stdmac[] = { "%define __SECT__ [section .text]", "%macro __NASM_CDecl__ 1", "%endmacro", NULL};static int aout_set_info(enum geninfo type, char **val){ return 0;}#endif /* OF_AOUT || OF_AOUTB */#ifdef OF_AOUTstruct ofmt of_aout = { "Linux a.out object files", "aout", NULL, null_debug_arr, &null_debug_form, aout_stdmac, aout_init, aout_set_info, aout_out, aout_deflabel, aout_section_names, aout_segbase, aout_directive, aout_filename, aout_cleanup};#endif#ifdef OF_AOUTBstruct ofmt of_aoutb = { "NetBSD/FreeBSD a.out object files", "aoutb", NULL, null_debug_arr, &null_debug_form, aout_stdmac, aoutb_init, aout_set_info, aout_out, aout_deflabel, aout_section_names, aout_segbase, aout_directive, aout_filename, aout_cleanup};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -