home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / nasm097s.zip / OUTELF.C < prev    next >
C/C++ Source or Header  |  1997-11-02  |  30KB  |  1,045 lines

  1. /* outelf.c    output routines for the Netwide Assembler to produce
  2.  *        ELF32 (i386 of course) object file format
  3.  *
  4.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  5.  * Julian Hall. All rights reserved. The software is
  6.  * redistributable under the licence given in the file "Licence"
  7.  * distributed in the NASM archive.
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #include "nasm.h"
  16. #include "nasmlib.h"
  17. #include "outform.h"
  18.  
  19. #ifdef OF_ELF
  20.  
  21. /*
  22.  * Relocation types.
  23.  */
  24. #define R_386_32 1               /* ordinary absolute relocation */
  25. #define R_386_PC32 2               /* PC-relative relocation */
  26. #define R_386_GOT32 3               /* an offset into GOT */
  27. #define R_386_PLT32 4               /* a PC-relative offset into PLT */
  28. #define R_386_GOTOFF 9               /* an offset from GOT base */
  29. #define R_386_GOTPC 10               /* a PC-relative offset _to_ GOT */
  30.  
  31. struct Reloc {
  32.     struct Reloc *next;
  33.     long address;               /* relative to _start_ of section */
  34.     long symbol;               /* ELF symbol info thingy */
  35.     int type;                   /* type of relocation */
  36. };
  37.  
  38. struct Symbol {
  39.     long strpos;               /* string table position of name */
  40.     long section;               /* section ID of the symbol */
  41.     int type;                   /* symbol type */
  42.     long value;                   /* address, or COMMON variable align */
  43.     long size;                   /* size of symbol */
  44.     long globnum;               /* symbol table offset if global */
  45.     struct Symbol *next;           /* list of globals in each section */
  46.     struct Symbol *nextfwd;           /* list of unresolved-size symbols */
  47.     char *name;                   /* used temporarily if in above list */
  48. };
  49.  
  50. #define SHT_PROGBITS 1
  51. #define SHT_NOBITS 8
  52.  
  53. #define SHF_WRITE 1
  54. #define SHF_ALLOC 2
  55. #define SHF_EXECINSTR 4
  56.  
  57. struct Section {
  58.     struct SAA *data;
  59.     unsigned long len, size, nrelocs;
  60.     long index;
  61.     int type;                   /* SHT_PROGBITS or SHT_NOBITS */
  62.     int align;                   /* alignment: power of two */
  63.     unsigned long flags;           /* section flags */
  64.     char *name;
  65.     struct SAA *rel;
  66.     long rellen;
  67.     struct Reloc *head, **tail;
  68.     struct Symbol *gsyms;           /* global symbols in section */
  69. };
  70.  
  71. #define SECT_DELTA 32
  72. static struct Section **sects;
  73. static int nsects, sectlen;
  74.  
  75. #define SHSTR_DELTA 256
  76. static char *shstrtab;
  77. static int shstrtablen, shstrtabsize;
  78.  
  79. static struct SAA *syms;
  80. static unsigned long nlocals, nglobs;
  81.  
  82. static long def_seg;
  83.  
  84. static struct RAA *bsym;
  85.  
  86. static struct SAA *strs;
  87. static unsigned long strslen;
  88.  
  89. static FILE *elffp;
  90. static efunc error;
  91. static evalfunc evaluate;
  92.  
  93. static struct Symbol *fwds;
  94.  
  95. static char elf_module[FILENAME_MAX];
  96.  
  97. extern struct ofmt of_elf;
  98.  
  99. #define SHN_ABS 0xFFF1
  100. #define SHN_COMMON 0xFFF2
  101. #define SHN_UNDEF 0
  102.  
  103. #define SYM_SECTION 0x04
  104. #define SYM_GLOBAL 0x10
  105. #define SYM_DATA 0x01
  106. #define SYM_FUNCTION 0x02
  107.  
  108. #define GLOBAL_TEMP_BASE 6           /* bigger than any constant sym id */
  109.  
  110. #define SEG_ALIGN 16               /* alignment of sections in file */
  111. #define SEG_ALIGN_1 (SEG_ALIGN-1)
  112.  
  113. static const char align_str[SEG_ALIGN] = ""; /* ANSI will pad this with 0s */
  114.  
  115. #define ELF_MAX_SECTIONS 16           /* really 10, but let's play safe */
  116. static struct ELF_SECTDATA {
  117.     void *data;
  118.     long len;
  119.     int is_saa;
  120. } elf_sects[ELF_MAX_SECTIONS];
  121. static int elf_nsect;
  122. static long elf_foffs;
  123.  
  124. static void elf_write(void);
  125. static void elf_sect_write(struct Section *, unsigned char *, unsigned long);
  126. static void elf_section_header (int, int, int, void *, int, long,
  127.                 int, int, int, int);
  128. static void elf_write_sections (void);
  129. static struct SAA *elf_build_symtab (long *, long *);
  130. static struct SAA *elf_build_reltab (long *, struct Reloc *);
  131. static void add_sectname (char *, char *);
  132.  
  133. /*
  134.  * Special section numbers which are used to define ELF special
  135.  * symbols, which can be used with WRT to provide PIC relocation
  136.  * types.
  137.  */
  138. static long elf_gotpc_sect, elf_gotoff_sect;
  139. static long elf_got_sect, elf_plt_sect;
  140. static long elf_sym_sect;
  141.  
  142. static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {
  143.     elffp = fp;
  144.     error = errfunc;
  145.     evaluate = eval;
  146.     (void) ldef;               /* placate optimisers */
  147.     sects = NULL;
  148.     nsects = sectlen = 0;
  149.     syms = saa_init((long)sizeof(struct Symbol));
  150.     nlocals = nglobs = 0;
  151.     bsym = raa_init();
  152.     strs = saa_init(1L);
  153.     saa_wbytes (strs, "\0", 1L);
  154.     saa_wbytes (strs, elf_module, (long)(strlen(elf_module)+1));
  155.     strslen = 2+strlen(elf_module);
  156.     shstrtab = NULL;
  157.     shstrtablen = shstrtabsize = 0;;
  158.     add_sectname ("", "");
  159.  
  160.     fwds = NULL;
  161.  
  162.     elf_gotpc_sect = seg_alloc();
  163.     ldef("..gotpc", elf_gotpc_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
  164.     elf_gotoff_sect = seg_alloc();
  165.     ldef("..gotoff", elf_gotoff_sect+1, 0L, NULL, FALSE, FALSE,&of_elf,error);
  166.     elf_got_sect = seg_alloc();
  167.     ldef("..got", elf_got_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
  168.     elf_plt_sect = seg_alloc();
  169.     ldef("..plt", elf_plt_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
  170.     elf_sym_sect = seg_alloc();
  171.     ldef("..sym", elf_sym_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);
  172.  
  173.     def_seg = seg_alloc();
  174. }
  175.  
  176. static void elf_cleanup(void) {
  177.     struct Reloc *r;
  178.     int i;
  179.  
  180.     elf_write();
  181.     fclose (elffp);
  182.     for (i=0; i<nsects; i++) {
  183.     if (sects[i]->type != SHT_NOBITS)
  184.         saa_free (sects[i]->data);
  185.     if (sects[i]->head)
  186.         saa_free (sects[i]->rel);
  187.     while (sects[i]->head) {
  188.         r = sects[i]->head;
  189.         sects[i]->head = sects[i]->head->next;
  190.         nasm_free (r);
  191.     }
  192.     }
  193.     nasm_free (sects);
  194.     saa_free (syms);
  195.     raa_free (bsym);
  196.     saa_free (strs);
  197. }
  198.  
  199. static void add_sectname (char *firsthalf, char *secondhalf) {
  200.     int len = strlen(firsthalf)+strlen(secondhalf);
  201.     while (shstrtablen + len + 1 > shstrtabsize)
  202.     shstrtab = nasm_realloc (shstrtab, (shstrtabsize += SHSTR_DELTA));
  203.     strcpy (shstrtab+shstrtablen, firsthalf);
  204.     strcat (shstrtab+shstrtablen, secondhalf);
  205.     shstrtablen += len+1;
  206. }
  207.  
  208. static int elf_make_section (char *name, int type, int flags, int align) {
  209.     struct Section *s;
  210.  
  211.     s = nasm_malloc (sizeof(*s));
  212.  
  213.     if (type != SHT_NOBITS)
  214.     s->data = saa_init (1L);
  215.     s->head = NULL;
  216.     s->tail = &s->head;
  217.     s->len = s->size = 0;
  218.     s->nrelocs = 0;
  219.     if (!strcmp(name, ".text"))
  220.     s->index = def_seg;
  221.     else
  222.     s->index = seg_alloc();
  223.     add_sectname ("", name);
  224.     s->name = nasm_malloc (1+strlen(name));
  225.     strcpy (s->name, name);
  226.     s->type = type;
  227.     s->flags = flags;
  228.     s->align = align;
  229.     s->gsyms = NULL;
  230.  
  231.     if (nsects >= sectlen)
  232.     sects = nasm_realloc (sects, (sectlen += SECT_DELTA)*sizeof(*sects));
  233.     sects[nsects++] = s;
  234.  
  235.     return nsects-1;
  236. }
  237.  
  238. static long elf_section_names (char *name, int pass, int *bits) {
  239.     char *p;
  240.     int flags_and, flags_or, type, align, i;
  241.  
  242.     /*
  243.      * Default is 32 bits.
  244.      */
  245.     if (!name)
  246.     *bits = 32;
  247.  
  248.     if (!name)
  249.     return def_seg;
  250.  
  251.     p = name;
  252.     while (*p && !isspace(*p)) p++;
  253.     if (*p) *p++ = '\0';
  254.     flags_and = flags_or = type = align = 0;
  255.  
  256.     while (*p && isspace(*p)) p++;
  257.     while (*p) {
  258.     char *q = p;
  259.     while (*p && !isspace(*p)) p++;
  260.     if (*p) *p++ = '\0';
  261.     while (*p && isspace(*p)) p++;
  262.     
  263.     if (!nasm_strnicmp(q, "align=", 6)) {
  264.         align = atoi(q+6);
  265.         if (align == 0)
  266.         align = 1;
  267.         if ( (align-1) & align ) {   /* means it's not a power of two */
  268.         error (ERR_NONFATAL, "section alignment %d is not"
  269.                " a power of two", align);
  270.         align = 1;
  271.         }
  272.     } else if (!nasm_stricmp(q, "alloc")) {
  273.         flags_and |= SHF_ALLOC;
  274.         flags_or |= SHF_ALLOC;
  275.     } else if (!nasm_stricmp(q, "noalloc")) {
  276.         flags_and |= SHF_ALLOC;
  277.         flags_or &= ~SHF_ALLOC;
  278.     } else if (!nasm_stricmp(q, "exec")) {
  279.         flags_and |= SHF_EXECINSTR;
  280.         flags_or |= SHF_EXECINSTR;
  281.     } else if (!nasm_stricmp(q, "noexec")) {
  282.         flags_and |= SHF_EXECINSTR;
  283.         flags_or &= ~SHF_EXECINSTR;
  284.     } else if (!nasm_stricmp(q, "write")) {
  285.         flags_and |= SHF_WRITE;
  286.         flags_or |= SHF_WRITE;
  287.     } else if (!nasm_stricmp(q, "nowrite")) {
  288.         flags_and |= SHF_WRITE;
  289.         flags_or &= ~SHF_WRITE;
  290.     } else if (!nasm_stricmp(q, "progbits")) {
  291.         type = SHT_PROGBITS;
  292.     } else if (!nasm_stricmp(q, "nobits")) {
  293.         type = SHT_NOBITS;
  294.     }
  295.     }
  296.  
  297.     if (!strcmp(name, ".comment") ||
  298.     !strcmp(name, ".shstrtab") ||
  299.     !strcmp(name, ".symtab") ||
  300.     !strcmp(name, ".strtab")) {
  301.     error (ERR_NONFATAL, "attempt to redefine reserved section"
  302.            "name `%s'", name);
  303.     return NO_SEG;
  304.     }
  305.  
  306.     for (i=0; i<nsects; i++)
  307.     if (!strcmp(name, sects[i]->name))
  308.         break;
  309.     if (i == nsects) {
  310.     if (!strcmp(name, ".text"))
  311.         i = elf_make_section (name, SHT_PROGBITS,
  312.                   SHF_ALLOC | SHF_EXECINSTR, 16);
  313.     else if (!strcmp(name, ".data"))
  314.         i = elf_make_section (name, SHT_PROGBITS,
  315.                   SHF_ALLOC | SHF_WRITE, 4);
  316.     else if (!strcmp(name, ".bss"))
  317.         i = elf_make_section (name, SHT_NOBITS,
  318.                   SHF_ALLOC | SHF_WRITE, 4);
  319.     else
  320.         i = elf_make_section (name, SHT_PROGBITS, SHF_ALLOC, 1);
  321.     if (type)
  322.         sects[i]->type = type;
  323.     if (align)
  324.         sects[i]->align = align;
  325.     sects[i]->flags &= ~flags_and;
  326.     sects[i]->flags |= flags_or;
  327.     } else if (pass == 1) {
  328.     if (type || align || flags_and)
  329.         error (ERR_WARNING, "section attributes ignored on"
  330.            " redeclaration of section `%s'", name);
  331.     }
  332.  
  333.     return sects[i]->index;
  334. }
  335.  
  336. static void elf_deflabel (char *name, long segment, long offset,
  337.                int is_global, char *special) {
  338.     int pos = strslen;
  339.     struct Symbol *sym;
  340.     int special_used = FALSE;
  341.  
  342.     if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
  343.     /*
  344.      * This is a NASM special symbol. We never allow it into
  345.      * the ELF symbol table, even if it's a valid one. If it
  346.      * _isn't_ a valid one, we should barf immediately.
  347.      */
  348.     if (strcmp(name, "..gotpc") && strcmp(name, "..gotoff") &&
  349.         strcmp(name, "..got") && strcmp(name, "..plt") &&
  350.         strcmp(name, "..sym"))
  351.         error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
  352.     return;
  353.     }
  354.  
  355.     if (is_global == 3) {
  356.     struct Symbol **s;
  357.     /*
  358.      * Fix up a forward-reference symbol size from the first
  359.      * pass.
  360.      */
  361.     for (s = &fwds; *s; s = &(*s)->nextfwd)
  362.         if (!strcmp((*s)->name, name)) {
  363.         struct tokenval tokval;
  364.         expr *e;
  365.         char *p = special;
  366.  
  367.         while (*p && !isspace(*p)) p++;
  368.         while (*p && isspace(*p)) p++;
  369.         stdscan_reset();
  370.         stdscan_bufptr = p;
  371.         tokval.t_type = TOKEN_INVALID;
  372.         e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
  373.         if (e) {
  374.             if (!is_simple(e))
  375.             error (ERR_NONFATAL, "cannot use relocatable"
  376.                    " expression as symbol size");
  377.             else
  378.             (*s)->size = reloc_value(e);
  379.         }
  380.  
  381.         /*
  382.          * Remove it from the list of unresolved sizes.
  383.          */
  384.         nasm_free ((*s)->name);
  385.         *s = (*s)->nextfwd;
  386.         return;
  387.         }
  388.     return;                   /* it wasn't an important one */
  389.     }
  390.  
  391.     saa_wbytes (strs, name, (long)(1+strlen(name)));
  392.     strslen += 1+strlen(name);
  393.  
  394.     sym = saa_wstruct (syms);
  395.  
  396.     sym->strpos = pos;
  397.     sym->type = is_global ? SYM_GLOBAL : 0;
  398.     sym->size = 0;
  399.     if (segment == NO_SEG)
  400.     sym->section = SHN_ABS;
  401.     else {
  402.     int i;
  403.     sym->section = SHN_UNDEF;
  404.     if (nsects == 0 && segment == def_seg) {
  405.         int tempint;
  406.         if (segment != elf_section_names (".text", 2, &tempint))
  407.         error (ERR_PANIC, "strange segment conditions in ELF driver");
  408.         sym->section = nsects;
  409.     } else {
  410.         for (i=0; i<nsects; i++)
  411.         if (segment == sects[i]->index) {
  412.             sym->section = i+1;
  413.             break;
  414.         }
  415.     }
  416.     }
  417.  
  418.     if (is_global == 2) {
  419.     sym->size = offset;
  420.     sym->value = 0;
  421.     sym->section = SHN_COMMON;
  422.     /*
  423.      * We have a common variable. Check the special text to see
  424.      * if it's a valid number and power of two; if so, store it
  425.      * as the alignment for the common variable.
  426.      */
  427.     if (special) {
  428.         int err;
  429.         sym->value = readnum (special, &err);
  430.         if (err)
  431.         error(ERR_NONFATAL, "alignment constraint `%s' is not a"
  432.               " valid number", special);
  433.         else if ( (sym->value | (sym->value-1)) != 2*sym->value - 1)
  434.         error(ERR_NONFATAL, "alignment constraint `%s' is not a"
  435.               " power of two", special);
  436.     }
  437.     special_used = TRUE;
  438.     } else
  439.     sym->value = (sym->section == SHN_UNDEF ? 0 : offset);
  440.  
  441.     if (sym->type == SYM_GLOBAL) {
  442.     if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON)
  443.         bsym = raa_write (bsym, segment, nglobs);
  444.     else {
  445.         /*
  446.          * This is a global symbol; so we must add it to the linked
  447.          * list of global symbols in its section. We'll push it on
  448.          * the beginning of the list, because it doesn't matter
  449.          * much which end we put it on and it's easier like this.
  450.          *
  451.          * In addition, we check the special text for symbol
  452.          * type and size information.
  453.          */
  454.         sym->next = sects[sym->section-1]->gsyms;
  455.         sects[sym->section-1]->gsyms = sym;
  456.  
  457.         if (special) {
  458.         int n = strcspn(special, " ");
  459.  
  460.         if (!nasm_strnicmp(special, "function", n))
  461.             sym->type |= SYM_FUNCTION;
  462.         else if (!nasm_strnicmp(special, "data", n) ||
  463.              !nasm_strnicmp(special, "object", n))
  464.             sym->type |= SYM_DATA;
  465.         else
  466.             error(ERR_NONFATAL, "unrecognised symbol type `%.*s'",
  467.               n, special);
  468.         if (special[n]) {
  469.             struct tokenval tokval;
  470.             expr *e;
  471.             int fwd = FALSE;
  472.  
  473.             while (special[n] && isspace(special[n]))
  474.             n++;
  475.             /*
  476.              * We have a size expression; attempt to
  477.              * evaluate it.
  478.              */
  479.             stdscan_reset();
  480.             stdscan_bufptr = special+n;
  481.             tokval.t_type = TOKEN_INVALID;
  482.             e = evaluate(stdscan, NULL, &tokval, &fwd, 0, error, NULL);
  483.             if (fwd) {
  484.             sym->nextfwd = fwds;
  485.             fwds = sym;
  486.             sym->name = nasm_strdup(name);
  487.             } else if (e) {
  488.             if (!is_simple(e))
  489.                 error (ERR_NONFATAL, "cannot use relocatable"
  490.                    " expression as symbol size");
  491.             else
  492.                 sym->size = reloc_value(e);
  493.             }
  494.         }
  495.         special_used = TRUE;
  496.         }
  497.     }
  498.     sym->globnum = nglobs;
  499.     nglobs++;
  500.     } else
  501.     nlocals++;
  502.  
  503.     if (special && !special_used)
  504.     error(ERR_NONFATAL, "no special symbol features supported here");
  505. }
  506.  
  507. static void elf_add_reloc (struct Section *sect, long segment,
  508.                int type) {
  509.     struct Reloc *r;
  510.  
  511.     r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
  512.     sect->tail = &r->next;
  513.     r->next = NULL;
  514.  
  515.     r->address = sect->len;
  516.     if (segment == NO_SEG)
  517.     r->symbol = 2;
  518.     else {
  519.     int i;
  520.     r->symbol = 0;
  521.     for (i=0; i<nsects; i++)
  522.         if (segment == sects[i]->index)
  523.         r->symbol = i+3;
  524.     if (!r->symbol)
  525.         r->symbol = GLOBAL_TEMP_BASE + raa_read(bsym, segment);
  526.     }
  527.     r->type = type;
  528.  
  529.     sect->nrelocs++;
  530. }
  531.  
  532. /*
  533.  * This routine deals with ..got and ..sym relocations: the more
  534.  * complicated kinds. In shared-library writing, some relocations
  535.  * with respect to global symbols must refer to the precise symbol
  536.  * rather than referring to an offset from the base of the section
  537.  * _containing_ the symbol. Such relocations call to this routine,
  538.  * which searches the symbol list for the symbol in question.
  539.  *
  540.  * R_386_GOT32 references require the _exact_ symbol address to be
  541.  * used; R_386_32 references can be at an offset from the symbol.
  542.  * The boolean argument `exact' tells us this.
  543.  *
  544.  * Return value is the adjusted value of `addr', having become an
  545.  * offset from the symbol rather than the section. Should always be
  546.  * zero when returning from an exact call.
  547.  *
  548.  * Limitation: if you define two symbols at the same place,
  549.  * confusion will occur.
  550.  *
  551.  * Inefficiency: we search, currently, using a linked list which
  552.  * isn't even necessarily sorted.
  553.  */
  554. static long elf_add_gsym_reloc (struct Section *sect,
  555.                 long segment, long offset,
  556.                 int type, int exact) {
  557.     struct Reloc *r;
  558.     struct Section *s;
  559.     struct Symbol *sym, *sm;
  560.     int i;
  561.  
  562.     /*
  563.      * First look up the segment/offset pair and find a global
  564.      * symbol corresponding to it. If it's not one of our segments,
  565.      * then it must be an external symbol, in which case we're fine
  566.      * doing a normal elf_add_reloc after first sanity-checking
  567.      * that the offset from the symbol is zero.
  568.      */
  569.     s = NULL;
  570.     for (i=0; i<nsects; i++)
  571.     if (segment == sects[i]->index) {
  572.         s = sects[i];
  573.         break;
  574.     }
  575.     if (!s) {
  576.     if (exact && offset != 0)
  577.         error (ERR_NONFATAL, "unable to find a suitable global symbol"
  578.            " for this reference");
  579.     else
  580.         elf_add_reloc (sect, segment, type);
  581.     return offset;
  582.     }
  583.  
  584.     if (exact) {
  585.     /*
  586.      * Find a symbol pointing _exactly_ at this one.
  587.      */
  588.     for (sym = s->gsyms; sym; sym = sym->next)
  589.         if (sym->value == offset)
  590.         break;
  591.     } else {
  592.     /*
  593.      * Find the nearest symbol below this one.
  594.      */
  595.     sym = NULL;
  596.     for (sm = s->gsyms; sm; sm = sm->next)
  597.         if (sm->value <= offset && (!sym || sm->value > sym->value))
  598.         sym = sm;
  599.     }
  600.     if (!sym && exact) {
  601.     error (ERR_NONFATAL, "unable to find a suitable global symbol"
  602.            " for this reference");
  603.     return 0;
  604.     }
  605.  
  606.     r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
  607.     sect->tail = &r->next;
  608.     r->next = NULL;
  609.  
  610.     r->address = sect->len;
  611.     r->symbol = GLOBAL_TEMP_BASE + sym->globnum;
  612.     r->type = type;
  613.  
  614.     sect->nrelocs++;
  615.  
  616.     return offset - sym->value;
  617. }
  618.  
  619. static void elf_out (long segto, void *data, unsigned long type,
  620.               long segment, long wrt) {
  621.     struct Section *s;
  622.     long realbytes = type & OUT_SIZMASK;
  623.     long addr;
  624.     unsigned char mydata[4], *p;
  625.     int i;
  626.  
  627.     type &= OUT_TYPMASK;
  628.  
  629.     /*
  630.      * handle absolute-assembly (structure definitions)
  631.      */
  632.     if (segto == NO_SEG) {
  633.     if (type != OUT_RESERVE)
  634.         error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
  635.            " space");
  636.     return;
  637.     }
  638.  
  639.     s = NULL;
  640.     for (i=0; i<nsects; i++)
  641.     if (segto == sects[i]->index) {
  642.         s = sects[i];
  643.         break;
  644.     }
  645.     if (!s) {
  646.     int tempint;               /* ignored */
  647.     if (segto != elf_section_names (".text", 2, &tempint))
  648.         error (ERR_PANIC, "strange segment conditions in ELF driver");
  649.     else
  650.         s = sects[nsects-1];
  651.     }
  652.  
  653.     if (s->type == SHT_NOBITS && type != OUT_RESERVE) {
  654.     error(ERR_WARNING, "attempt to initialise memory in"
  655.           " BSS section `%s': ignored", s->name);
  656.     if (type == OUT_REL2ADR)
  657.         realbytes = 2;
  658.     else if (type == OUT_REL4ADR)
  659.         realbytes = 4;
  660.     s->len += realbytes;
  661.     return;
  662.     }
  663.  
  664.     if (type == OUT_RESERVE) {
  665.     if (s->type == SHT_PROGBITS) {
  666.         error(ERR_WARNING, "uninitialised space declared in"
  667.           " non-BSS section `%s': zeroing", s->name);
  668.         elf_sect_write (s, NULL, realbytes);
  669.     } else
  670.         s->len += realbytes;
  671.     } else if (type == OUT_RAWDATA) {
  672.     if (segment != NO_SEG)
  673.         error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
  674.     elf_sect_write (s, data, realbytes);
  675.     } else if (type == OUT_ADDRESS) {
  676.     addr = *(long *)data;
  677.     if (segment != NO_SEG) {
  678.         if (segment % 2) {
  679.         error(ERR_NONFATAL, "ELF format does not support"
  680.               " segment base references");
  681.         } else {
  682.         if (wrt == NO_SEG) {
  683.             elf_add_reloc (s, segment, R_386_32);
  684.         } else if (wrt == elf_gotpc_sect+1) {
  685.             /*
  686.              * The user will supply GOT relative to $$. ELF
  687.              * will let us have GOT relative to $. So we
  688.              * need to fix up the data item by $-$$.
  689.              */
  690.             addr += s->len;
  691.             elf_add_reloc (s, segment, R_386_GOTPC);
  692.         } else if (wrt == elf_gotoff_sect+1) {
  693.             elf_add_reloc (s, segment, R_386_GOTOFF);
  694.         } else if (wrt == elf_got_sect+1) {
  695.             addr = elf_add_gsym_reloc (s, segment, addr,
  696.                            R_386_GOT32, TRUE);
  697.         } else if (wrt == elf_sym_sect+1) {
  698.             addr = elf_add_gsym_reloc (s, segment, addr,
  699.                            R_386_32, FALSE);
  700.         } else if (wrt == elf_plt_sect+1) {
  701.             error(ERR_NONFATAL, "ELF format cannot produce non-PC-"
  702.               "relative PLT references");
  703.         } else {
  704.             error (ERR_NONFATAL, "ELF format does not support this"
  705.                " use of WRT");
  706.             wrt = NO_SEG;      /* we can at least _try_ to continue */
  707.         }
  708.         }
  709.     }
  710.     p = mydata;
  711.     if (realbytes != 4 && segment != NO_SEG)
  712.         error (ERR_NONFATAL, "ELF format does not support non-32-bit"
  713.            " relocations");
  714.     WRITELONG (p, addr);
  715.     elf_sect_write (s, mydata, realbytes);
  716.     } else if (type == OUT_REL2ADR) {
  717.     error (ERR_NONFATAL, "ELF format does not support 16-bit"
  718.            " relocations");
  719.     } else if (type == OUT_REL4ADR) {
  720.     if (segment == segto)
  721.         error(ERR_PANIC, "intra-segment OUT_REL4ADR");
  722.     if (segment != NO_SEG && segment % 2) {
  723.         error(ERR_NONFATAL, "ELF format does not support"
  724.           " segment base references");
  725.     } else {
  726.         if (wrt == NO_SEG) {
  727.         elf_add_reloc (s, segment, R_386_PC32);
  728.         } else if (wrt == elf_plt_sect+1) {
  729.         elf_add_reloc (s, segment, R_386_PLT32);
  730.         } else if (wrt == elf_gotpc_sect+1 ||
  731.                wrt == elf_gotoff_sect+1 ||
  732.                wrt == elf_got_sect+1) {
  733.         error(ERR_NONFATAL, "ELF format cannot produce PC-"
  734.               "relative GOT references");
  735.         } else {
  736.         error (ERR_NONFATAL, "ELF format does not support this"
  737.                " use of WRT");
  738.         wrt = NO_SEG;      /* we can at least _try_ to continue */
  739.         }
  740.     }
  741.     p = mydata;
  742.     WRITELONG (p, *(long*)data - realbytes);
  743.     elf_sect_write (s, mydata, 4L);
  744.     }
  745. }
  746.  
  747. static void elf_write(void) {
  748.     int nsections, align;
  749.     char *p;
  750.     int commlen;
  751.     char comment[64];
  752.     int i;
  753.  
  754.     struct SAA *symtab;
  755.     long symtablen, symtablocal;
  756.  
  757.     /*
  758.      * Work out how many sections we will have. We have SHN_UNDEF,
  759.      * then the flexible user sections, then the four fixed
  760.      * sections `.comment', `.shstrtab', `.symtab' and `.strtab',
  761.      * then optionally relocation sections for the user sections.
  762.      */
  763.     nsections = 5;               /* SHN_UNDEF and the fixed ones */
  764.     add_sectname ("", ".comment");
  765.     add_sectname ("", ".shstrtab");
  766.     add_sectname ("", ".symtab");
  767.     add_sectname ("", ".strtab");
  768.     for (i=0; i<nsects; i++) {
  769.     nsections++;               /* for the section itself */
  770.     if (sects[i]->head) {
  771.         nsections++;           /* for its relocations */
  772.         add_sectname (".rel", sects[i]->name);
  773.     }
  774.     }
  775.  
  776.     /*
  777.      * Do the comment.
  778.      */
  779.     *comment = '\0';
  780.     commlen = 2+sprintf(comment+1, "The Netwide Assembler %s", NASM_VER);
  781.  
  782.     /*
  783.      * Output the ELF header.
  784.      */
  785.     fwrite ("\177ELF\1\1\1\0\0\0\0\0\0\0\0\0", 16, 1, elffp);
  786.     fwriteshort (1, elffp);           /* ET_REL relocatable file */
  787.     fwriteshort (3, elffp);           /* EM_386 processor ID */
  788.     fwritelong (1L, elffp);           /* EV_CURRENT file format version */
  789.     fwritelong (0L, elffp);           /* no entry point */
  790.     fwritelong (0L, elffp);           /* no program header table */
  791.     fwritelong (0x40L, elffp);           /* section headers straight after
  792.                     * ELF header plus alignment */
  793.     fwritelong (0L, elffp);           /* 386 defines no special flags */
  794.     fwriteshort (0x34, elffp);           /* size of ELF header */
  795.     fwriteshort (0, elffp);           /* no program header table, again */
  796.     fwriteshort (0, elffp);           /* still no program header table */
  797.     fwriteshort (0x28, elffp);           /* size of section header */
  798.     fwriteshort (nsections, elffp);    /* number of sections */
  799.     fwriteshort (nsects+2, elffp);     /* string table section index for
  800.                     * section header table */
  801.     fwritelong (0L, elffp);           /* align to 0x40 bytes */
  802.     fwritelong (0L, elffp);
  803.     fwritelong (0L, elffp);
  804.  
  805.     /*
  806.      * Build the symbol table and relocation tables.
  807.      */
  808.     symtab = elf_build_symtab (&symtablen, &symtablocal);
  809.     for (i=0; i<nsects; i++)
  810.     if (sects[i]->head)
  811.         sects[i]->rel = elf_build_reltab (§s[i]->rellen,
  812.                           sects[i]->head);
  813.  
  814.     /*
  815.      * Now output the section header table.
  816.      */
  817.  
  818.     elf_foffs = 0x40 + 0x28 * nsections;
  819.     align = ((elf_foffs+SEG_ALIGN_1) & ~SEG_ALIGN_1) - elf_foffs;
  820.     elf_foffs += align;
  821.     elf_nsect = 0;
  822.  
  823.     elf_section_header (0, 0, 0, NULL, FALSE, 0L, 0, 0, 0, 0); /* SHN_UNDEF */
  824.     p = shstrtab+1;
  825.     for (i=0; i<nsects; i++) {
  826.     elf_section_header (p - shstrtab, sects[i]->type, sects[i]->flags,
  827.                 (sects[i]->type == SHT_PROGBITS ?
  828.                  sects[i]->data : NULL), TRUE,
  829.                 sects[i]->len, 0, 0, sects[i]->align, 0);
  830.     p += strlen(p)+1;
  831.     }
  832.     elf_section_header (p - shstrtab, 1, 0, comment, FALSE,
  833.             (long)commlen, 0, 0, 1, 0);/* .comment */
  834.     p += strlen(p)+1;
  835.     elf_section_header (p - shstrtab, 3, 0, shstrtab, FALSE,
  836.             (long)shstrtablen, 0, 0, 1, 0);/* .shstrtab */
  837.     p += strlen(p)+1;
  838.     elf_section_header (p - shstrtab, 2, 0, symtab, TRUE,
  839.             symtablen, nsects+4, symtablocal, 4, 16);/* .symtab */
  840.     p += strlen(p)+1;
  841.     elf_section_header (p - shstrtab, 3, 0, strs, TRUE,
  842.             strslen, 0, 0, 1, 0);        /* .strtab */
  843.     for (i=0; i<nsects; i++) if (sects[i]->head) {
  844.     p += strlen(p)+1;
  845.     elf_section_header (p - shstrtab, 9, 0, sects[i]->rel, TRUE,
  846.                 sects[i]->rellen, nsects+3, i+1, 4, 8);
  847.     }
  848.  
  849.     fwrite (align_str, align, 1, elffp);
  850.  
  851.     /*
  852.      * Now output the sections.
  853.      */
  854.     elf_write_sections();
  855.  
  856.     saa_free (symtab);
  857. }
  858.  
  859. static struct SAA *elf_build_symtab (long *len, long *local) {
  860.     struct SAA *s = saa_init(1L);
  861.     struct Symbol *sym;
  862.     unsigned char entry[16], *p;
  863.     int i;
  864.  
  865.     *len = *local = 0;
  866.  
  867.     /*
  868.      * First, an all-zeros entry, required by the ELF spec.
  869.      */
  870.     saa_wbytes (s, NULL, 16L);           /* null symbol table entry */
  871.     *len += 16;
  872.     (*local)++;
  873.  
  874.     /*
  875.      * Next, an entry for the file name.
  876.      */
  877.     p = entry;
  878.     WRITELONG (p, 1);               /* we know it's 1st thing in strtab */
  879.     WRITELONG (p, 0);               /* no value */
  880.     WRITELONG (p, 0);               /* no size either */
  881.     WRITESHORT (p, 4);               /* type FILE */
  882.     WRITESHORT (p, SHN_ABS);
  883.     saa_wbytes (s, entry, 16L);
  884.     *len += 16;
  885.     (*local)++;
  886.  
  887.     /*
  888.      * Now some standard symbols defining the segments, for relocation
  889.      * purposes.
  890.      */
  891.     for (i = 1; i <= nsects+1; i++) {
  892.     p = entry;
  893.     WRITELONG (p, 0);           /* no symbol name */
  894.     WRITELONG (p, 0);           /* offset zero */
  895.     WRITELONG (p, 0);           /* size zero */
  896.     WRITESHORT (p, 3);           /* local section-type thing */
  897.     WRITESHORT (p, (i==1 ? SHN_ABS : i-1));   /* the section id */
  898.     saa_wbytes (s, entry, 16L);
  899.     *len += 16;
  900.     (*local)++;
  901.     }
  902.  
  903.     /*
  904.      * Now the other local symbols.
  905.      */
  906.     saa_rewind (syms);
  907.     while ( (sym = saa_rstruct (syms)) ) {
  908.     if (sym->type & SYM_GLOBAL)
  909.         continue;
  910.     p = entry;
  911.     WRITELONG (p, sym->strpos);
  912.     WRITELONG (p, sym->value);
  913.     WRITELONG (p, sym->size);
  914.     WRITESHORT (p, sym->type);     /* local non-typed thing */
  915.     WRITESHORT (p, sym->section);
  916.     saa_wbytes (s, entry, 16L);
  917.         *len += 16;
  918.     (*local)++;
  919.     }
  920.  
  921.     /*
  922.      * Now the global symbols.
  923.      */
  924.     saa_rewind (syms);
  925.     while ( (sym = saa_rstruct (syms)) ) {
  926.     if (!(sym->type & SYM_GLOBAL))
  927.         continue;
  928.     p = entry;
  929.     WRITELONG (p, sym->strpos);
  930.     WRITELONG (p, sym->value);
  931.     WRITELONG (p, sym->size);
  932.     WRITESHORT (p, sym->type);     /* global non-typed thing */
  933.     WRITESHORT (p, sym->section);
  934.     saa_wbytes (s, entry, 16L);
  935.     *len += 16;
  936.     }
  937.  
  938.     return s;
  939. }
  940.  
  941. static struct SAA *elf_build_reltab (long *len, struct Reloc *r) {
  942.     struct SAA *s;
  943.     unsigned char *p, entry[8];
  944.  
  945.     if (!r)
  946.     return NULL;
  947.  
  948.     s = saa_init(1L);
  949.     *len = 0;
  950.  
  951.     while (r) {
  952.     long sym = r->symbol;
  953.  
  954.     if (sym >= GLOBAL_TEMP_BASE)
  955.         sym += -GLOBAL_TEMP_BASE + (nsects+3) + nlocals;
  956.  
  957.     p = entry;
  958.     WRITELONG (p, r->address);
  959.     WRITELONG (p, (sym << 8) + r->type);
  960.     saa_wbytes (s, entry, 8L);
  961.     *len += 8;
  962.  
  963.     r = r->next;
  964.     }
  965.  
  966.     return s;
  967. }
  968.  
  969. static void elf_section_header (int name, int type, int flags,
  970.                 void *data, int is_saa, long datalen,
  971.                 int link, int info, int align, int eltsize) {
  972.     elf_sects[elf_nsect].data = data;
  973.     elf_sects[elf_nsect].len = datalen;
  974.     elf_sects[elf_nsect].is_saa = is_saa;
  975.     elf_nsect++;
  976.  
  977.     fwritelong ((long)name, elffp);
  978.     fwritelong ((long)type, elffp);
  979.     fwritelong ((long)flags, elffp);
  980.     fwritelong (0L, elffp);           /* no address, ever, in object files */
  981.     fwritelong (type == 0 ? 0L : elf_foffs, elffp);
  982.     fwritelong (datalen, elffp);
  983.     if (data)
  984.     elf_foffs += (datalen+SEG_ALIGN_1) & ~SEG_ALIGN_1;
  985.     fwritelong ((long)link, elffp);
  986.     fwritelong ((long)info, elffp);
  987.     fwritelong ((long)align, elffp);
  988.     fwritelong ((long)eltsize, elffp);
  989. }
  990.  
  991. static void elf_write_sections (void) {
  992.     int i;
  993.     for (i = 0; i < elf_nsect; i++)
  994.     if (elf_sects[i].data) {
  995.         long len = elf_sects[i].len;
  996.         long reallen = (len+SEG_ALIGN_1) & ~SEG_ALIGN_1;
  997.         long align = reallen - len;
  998.         if (elf_sects[i].is_saa)
  999.         saa_fpwrite (elf_sects[i].data, elffp);
  1000.         else
  1001.         fwrite (elf_sects[i].data, len, 1, elffp);
  1002.         fwrite (align_str, align, 1, elffp);
  1003.     }
  1004. }
  1005.  
  1006. static void elf_sect_write (struct Section *sect,
  1007.                  unsigned char *data, unsigned long len) {
  1008.     saa_wbytes (sect->data, data, len);
  1009.     sect->len += len;
  1010. }
  1011.  
  1012. static long elf_segbase (long segment) {
  1013.     return segment;
  1014. }
  1015.  
  1016. static int elf_directive (char *directive, char *value, int pass) {
  1017.     return 0;
  1018. }
  1019.  
  1020. static void elf_filename (char *inname, char *outname, efunc error) {
  1021.     strcpy(elf_module, inname);
  1022.     standard_extension (inname, outname, ".o", error);
  1023. }
  1024.  
  1025. static char *elf_stdmac[] = {
  1026.     "%define __SECT__ [section .text]",
  1027.     NULL
  1028. };
  1029.  
  1030. struct ofmt of_elf = {
  1031.     "ELF32 (i386) object files (e.g. Linux)",
  1032.     "elf",
  1033.     elf_stdmac,
  1034.     elf_init,
  1035.     elf_out,
  1036.     elf_deflabel,
  1037.     elf_section_names,
  1038.     elf_segbase,
  1039.     elf_directive,
  1040.     elf_filename,
  1041.     elf_cleanup
  1042. };
  1043.  
  1044. #endif /* OF_ELF */
  1045.