/* ----------------------------------------------------------------------- * * * Copyright 1996-2013 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ----------------------------------------------------------------------- */ /* * outaout.c output routines for the Netwide Assembler to produce * Linux a.out object files */ #include "compiler.h" #include "nctype.h" #include "nasm.h" #include "nasmlib.h" #include "error.h" #include "saa.h" #include "raa.h" #include "stdscan.h" #include "eval.h" #include "outform.h" #include "outlib.h" #if defined OF_AOUT || defined OF_AOUTB #define RELTYPE_ABSOLUTE … #define RELTYPE_RELATIVE … #define RELTYPE_GOTPC … #define RELTYPE_GOTOFF … #define RELTYPE_GOT … #define RELTYPE_PLT … #define RELTYPE_SYMFLAG … struct Reloc { … }; struct Symbol { … }; /* * Section IDs - used in Reloc.symbol when negative, and in * Symbol.type when positive. */ #define SECT_ABS … #define SECT_TEXT … #define SECT_DATA … #define SECT_BSS … #define SECT_MASK … /* * More flags used in Symbol.type. */ #define SYM_GLOBAL … #define SYM_DATA … #define SYM_FUNCTION … #define SYM_WITH_SIZE … /* * Bit more explanation of symbol types: SECT_xxx denotes a local * symbol. SECT_xxx|SYM_GLOBAL denotes a global symbol, defined in * this module. Just SYM_GLOBAL, with zero value, denotes an * external symbol referenced in this module. And just SYM_GLOBAL, * but with a non-zero value, declares a C `common' variable, of * size `value'. */ struct Section { … }; static struct Section stext, sdata, sbss; static struct SAA *syms; static uint32_t nsyms; static struct RAA *bsym; static struct SAA *strs; static uint32_t strslen; static struct Symbol *fwds; static int bsd; static int is_pic; static void aout_write(void); static void aout_write_relocs(struct Reloc *); static void aout_write_syms(void); static void aout_sect_write(struct Section *, const uint8_t *, uint32_t); static void aout_pad_sections(void); static void aout_fixup_relocs(struct Section *); /* * Special section numbers which are used to define special * symbols, which can be used with WRT to provide PIC relocation * types. */ static int32_t aout_gotpc_sect, aout_gotoff_sect; static int32_t aout_got_sect, aout_plt_sect; static int32_t aout_sym_sect; static void aoutg_init(void) { … } #ifdef OF_AOUT static void aout_init(void) { … } #endif #ifdef OF_AOUTB extern const struct ofmt of_aoutb; static void aoutb_init(void) { … } #endif static void aout_cleanup(void) { … } static int32_t aout_section_names(char *name, int *bits) { … } static void aout_deflabel(char *name, int32_t segment, int64_t offset, int is_global, char *special) { … } static void aout_add_reloc(struct Section *sect, int32_t segment, int reltype, int bytes) { … } /* * This routine deals with ..got and ..sym relocations: the more * complicated kinds. In shared-library writing, some relocations * with respect to global symbols must refer to the precise symbol * rather than referring to an offset from the base of the section * _containing_ the symbol. Such relocations call to this routine, * which searches the symbol list for the symbol in question. * * RELTYPE_GOT references require the _exact_ symbol address to be * used; RELTYPE_ABSOLUTE references can be at an offset from the * symbol. The boolean argument `exact' tells us this. * * Return value is the adjusted value of `addr', having become an * offset from the symbol rather than the section. Should always be * zero when returning from an exact call. * * Limitation: if you define two symbols at the same place, * confusion will occur. * * Inefficiency: we search, currently, using a linked list which * isn't even necessarily sorted. */ static int32_t aout_add_gsym_reloc(struct Section *sect, int32_t segment, int32_t offset, int type, int bytes, int exact) { … } /* * 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 int32_t aout_add_gotoff_reloc(struct Section *sect, int32_t segment, int32_t offset, int bytes) { … } static void aout_out(int32_t segto, const void *data, enum out_type type, uint64_t size, int32_t segment, int32_t wrt) { … } static void aout_pad_sections(void) { … } /* * 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) { … } static void aout_write(void) { … } static void aout_write_relocs(struct Reloc *r) { … } static void aout_write_syms(void) { … } static void aout_sect_write(struct Section *sect, const uint8_t *data, uint32_t len) { … } extern macros_t aout_stdmac[]; #endif /* OF_AOUT || OF_AOUTB */ #ifdef OF_AOUT const struct ofmt of_aout = …; #endif #ifdef OF_AOUTB const struct ofmt of_aoutb = …; #endif