NASM 0.95
[platform/upstream/nasm.git] / outelf.c
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 struct Reloc {
22     struct Reloc *next;
23     long address;                      /* relative to _start_ of section */
24     long symbol;                       /* ELF symbol info thingy */
25     int relative;                      /* TRUE or FALSE */
26 };
27
28 struct Symbol {
29     long strpos;                       /* string table position of name */
30     long section;                      /* section ID of the symbol */
31     int type;                          /* TRUE or FALSE */
32     long value;                        /* address, or COMMON variable size */
33 };
34
35 #define SHT_PROGBITS 1
36 #define SHT_NOBITS 8
37
38 #define SHF_WRITE 1
39 #define SHF_ALLOC 2
40 #define SHF_EXECINSTR 4
41
42 struct Section {
43     struct SAA *data;
44     unsigned long len, size, nrelocs;
45     long index;
46     int type;                          /* SHT_PROGBITS or SHT_NOBITS */
47     int align;                         /* alignment: power of two */
48     unsigned long flags;               /* section flags */
49     char *name;
50     struct SAA *rel;
51     long rellen;
52     struct Reloc *head, **tail;
53 };
54
55 #define SECT_DELTA 32
56 static struct Section **sects;
57 static int nsects, sectlen;
58
59 #define SHSTR_DELTA 256
60 static char *shstrtab;
61 static int shstrtablen, shstrtabsize;
62
63 static struct SAA *syms;
64 static unsigned long nlocals, nglobs;
65
66 static long def_seg;
67
68 static struct RAA *bsym;
69
70 static struct SAA *strs;
71 static unsigned long strslen;
72
73 static FILE *elffp;
74 static efunc error;
75
76 static char elf_module[FILENAME_MAX];
77
78 #define SHN_ABS 0xFFF1
79 #define SHN_COMMON 0xFFF2
80 #define SHN_UNDEF 0
81
82 #define SYM_SECTION 0x04
83 #define SYM_GLOBAL 0x10
84
85 #define GLOBAL_TEMP_BASE 6             /* bigger than any constant sym id */
86
87 #define SEG_ALIGN 16                   /* alignment of sections in file */
88 #define SEG_ALIGN_1 (SEG_ALIGN-1)
89
90 static const char align_str[SEG_ALIGN] = ""; /* ANSI will pad this with 0s */
91
92 #define ELF_MAX_SECTIONS 16            /* really 10, but let's play safe */
93 static struct ELF_SECTDATA {
94     void *data;
95     long len;
96     int is_saa;
97 } elf_sects[ELF_MAX_SECTIONS];
98 static int elf_nsect;
99 static long elf_foffs;
100
101 static void elf_write(void);
102 static void elf_sect_write(struct Section *, unsigned char *, unsigned long);
103 static void elf_section_header (int, int, int, void *, int, long,
104                                 int, int, int, int);
105 static void elf_write_sections (void);
106 static struct SAA *elf_build_symtab (long *, long *);
107 static struct SAA *elf_build_reltab (long *, struct Reloc *);
108 static void add_sectname (char *, char *);
109
110 static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef) {
111     elffp = fp;
112     error = errfunc;
113     (void) ldef;                       /* placate optimisers */
114     sects = NULL;
115     nsects = sectlen = 0;
116     syms = saa_init((long)sizeof(struct Symbol));
117     nlocals = nglobs = 0;
118     bsym = raa_init();
119     strs = saa_init(1L);
120     saa_wbytes (strs, "\0", 1L);
121     saa_wbytes (strs, elf_module, (long)(strlen(elf_module)+1));
122     strslen = 2+strlen(elf_module);
123     shstrtab = NULL;
124     shstrtablen = shstrtabsize = 0;;
125     add_sectname ("", "");
126     def_seg = seg_alloc();
127 }
128
129 static void elf_cleanup(void) {
130     struct Reloc *r;
131     int i;
132
133     elf_write();
134     fclose (elffp);
135     for (i=0; i<nsects; i++) {
136         if (sects[i]->type != SHT_NOBITS)
137             saa_free (sects[i]->data);
138         if (sects[i]->head)
139             saa_free (sects[i]->rel);
140         while (sects[i]->head) {
141             r = sects[i]->head;
142             sects[i]->head = sects[i]->head->next;
143             nasm_free (r);
144         }
145     }
146     nasm_free (sects);
147     saa_free (syms);
148     raa_free (bsym);
149     saa_free (strs);
150 }
151
152 static void add_sectname (char *firsthalf, char *secondhalf) {
153     int len = strlen(firsthalf)+strlen(secondhalf);
154     while (shstrtablen + len + 1 > shstrtabsize)
155         shstrtab = nasm_realloc (shstrtab, (shstrtabsize += SHSTR_DELTA));
156     strcpy (shstrtab+shstrtablen, firsthalf);
157     strcat (shstrtab+shstrtablen, secondhalf);
158     shstrtablen += len+1;
159 }
160
161 static int elf_make_section (char *name, int type, int flags, int align) {
162     struct Section *s;
163
164     s = nasm_malloc (sizeof(*s));
165
166     if (type != SHT_NOBITS)
167         s->data = saa_init (1L);
168     s->head = NULL;
169     s->tail = &s->head;
170     s->len = s->size = 0;
171     s->nrelocs = 0;
172     if (!strcmp(name, ".text"))
173         s->index = def_seg;
174     else
175         s->index = seg_alloc();
176     add_sectname ("", name);
177     s->name = nasm_malloc (1+strlen(name));
178     strcpy (s->name, name);
179     s->type = type;
180     s->flags = flags;
181     s->align = align;
182
183     if (nsects >= sectlen)
184         sects = nasm_realloc (sects, (sectlen += SECT_DELTA)*sizeof(*sects));
185     sects[nsects++] = s;
186
187     return nsects-1;
188 }
189
190 static long elf_section_names (char *name, int pass, int *bits) {
191     char *p;
192     int flags_and, flags_or, type, align, i;
193
194     /*
195      * Default is 32 bits.
196      */
197     if (!name)
198         *bits = 32;
199
200     if (!name)
201         return def_seg;
202
203     p = name;
204     while (*p && !isspace(*p)) p++;
205     if (*p) *p++ = '\0';
206     flags_and = flags_or = type = align = 0;
207
208     while (*p && isspace(*p)) p++;
209     while (*p) {
210         char *q = p;
211         while (*p && !isspace(*p)) p++;
212         if (*p) *p++ = '\0';
213         while (*p && isspace(*p)) p++;
214         
215         if (!nasm_strnicmp(q, "align=", 6)) {
216             align = atoi(q+6);
217             if (align == 0)
218                 align = 1;
219             if ( (align-1) & align ) {   /* means it's not a power of two */
220                 error (ERR_NONFATAL, "section alignment %d is not"
221                        " a power of two", align);
222                 align = 1;
223             }
224         } else if (!nasm_stricmp(q, "alloc")) {
225             flags_and |= SHF_ALLOC;
226             flags_or |= SHF_ALLOC;
227         } else if (!nasm_stricmp(q, "noalloc")) {
228             flags_and |= SHF_ALLOC;
229             flags_or &= ~SHF_ALLOC;
230         } else if (!nasm_stricmp(q, "exec")) {
231             flags_and |= SHF_EXECINSTR;
232             flags_or |= SHF_EXECINSTR;
233         } else if (!nasm_stricmp(q, "noexec")) {
234             flags_and |= SHF_EXECINSTR;
235             flags_or &= ~SHF_EXECINSTR;
236         } else if (!nasm_stricmp(q, "write")) {
237             flags_and |= SHF_WRITE;
238             flags_or |= SHF_WRITE;
239         } else if (!nasm_stricmp(q, "nowrite")) {
240             flags_and |= SHF_WRITE;
241             flags_or &= ~SHF_WRITE;
242         } else if (!nasm_stricmp(q, "progbits")) {
243             type = SHT_PROGBITS;
244         } else if (!nasm_stricmp(q, "nobits")) {
245             type = SHT_NOBITS;
246         }
247     }
248
249     if (!strcmp(name, ".comment") ||
250         !strcmp(name, ".shstrtab") ||
251         !strcmp(name, ".symtab") ||
252         !strcmp(name, ".strtab")) {
253         error (ERR_NONFATAL, "attempt to redefine reserved section"
254                "name `%s'", name);
255         return NO_SEG;
256     }
257
258     for (i=0; i<nsects; i++)
259         if (!strcmp(name, sects[i]->name))
260             break;
261     if (i == nsects) {
262         if (!strcmp(name, ".text"))
263             i = elf_make_section (name, SHT_PROGBITS,
264                                   SHF_ALLOC | SHF_EXECINSTR, 16);
265         else if (!strcmp(name, ".data"))
266             i = elf_make_section (name, SHT_PROGBITS,
267                                   SHF_ALLOC | SHF_WRITE, 4);
268         else if (!strcmp(name, ".bss"))
269             i = elf_make_section (name, SHT_NOBITS,
270                                   SHF_ALLOC | SHF_WRITE, 4);
271         else
272             i = elf_make_section (name, SHT_PROGBITS, SHF_ALLOC, 1);
273         if (type)
274             sects[i]->type = type;
275         if (align)
276             sects[i]->align = align;
277         sects[i]->flags &= ~flags_and;
278         sects[i]->flags |= flags_or;
279     } else if (pass == 1) {
280         if (type || align || flags_and)
281             error (ERR_WARNING, "section attributes ignored on"
282                    " redeclaration of section `%s'", name);
283     }
284
285     return sects[i]->index;
286 }
287
288 static void elf_deflabel (char *name, long segment, long offset,
289                            int is_global) {
290     int pos = strslen;
291     struct Symbol *sym;
292
293     if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
294         error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
295         return;
296     }
297
298     saa_wbytes (strs, name, (long)(1+strlen(name)));
299     strslen += 1+strlen(name);
300
301     sym = saa_wstruct (syms);
302
303     sym->strpos = pos;
304     sym->type = is_global ? SYM_GLOBAL : 0;
305     if (segment == NO_SEG)
306         sym->section = SHN_ABS;
307     else {
308         int i;
309         sym->section = SHN_UNDEF;
310         if (nsects == 0 && segment == def_seg) {
311             int tempint;
312             if (segment != elf_section_names (".text", 2, &tempint))
313                 error (ERR_PANIC, "strange segment conditions in ELF driver");
314             sym->section = nsects;
315         } else {
316             for (i=0; i<nsects; i++)
317                 if (segment == sects[i]->index) {
318                     sym->section = i+1;
319                     break;
320                 }
321         }
322     }
323
324     if (is_global == 2) {
325         sym->value = offset;
326         sym->section = SHN_COMMON;
327     } else
328         sym->value = (sym->section == SHN_UNDEF ? 0 : offset);
329
330     if (sym->type == SYM_GLOBAL) {
331         if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON)
332             bsym = raa_write (bsym, segment, nglobs);
333         nglobs++;
334     } else
335         nlocals++;
336 }
337
338 static void elf_add_reloc (struct Section *sect, long segment,
339                             int relative) {
340     struct Reloc *r;
341
342     r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
343     sect->tail = &r->next;
344     r->next = NULL;
345
346     r->address = sect->len;
347     if (segment == NO_SEG)
348         r->symbol = 2;
349     else {
350         int i;
351         r->symbol = 0;
352         for (i=0; i<nsects; i++)
353             if (segment == sects[i]->index)
354                 r->symbol = i+3;
355         if (!r->symbol)
356             r->symbol = GLOBAL_TEMP_BASE + raa_read(bsym, segment);
357     }
358     r->relative = relative;
359
360     sect->nrelocs++;
361 }
362
363 static void elf_out (long segto, void *data, unsigned long type,
364                       long segment, long wrt) {
365     struct Section *s;
366     long realbytes = type & OUT_SIZMASK;
367     unsigned char mydata[4], *p;
368     int i;
369
370     if (wrt != NO_SEG) {
371         wrt = NO_SEG;                  /* continue to do _something_ */
372         error (ERR_NONFATAL, "WRT not supported by ELF output format");
373     }
374
375     type &= OUT_TYPMASK;
376
377     /*
378      * handle absolute-assembly (structure definitions)
379      */
380     if (segto == NO_SEG) {
381         if (type != OUT_RESERVE)
382             error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
383                    " space");
384         return;
385     }
386
387     s = NULL;
388     for (i=0; i<nsects; i++)
389         if (segto == sects[i]->index) {
390             s = sects[i];
391             break;
392         }
393     if (!s) {
394         int tempint;                   /* ignored */
395         if (segto != elf_section_names (".text", 2, &tempint))
396             error (ERR_PANIC, "strange segment conditions in ELF driver");
397         else
398             s = sects[nsects-1];
399     }
400
401     if (s->type == SHT_NOBITS && type != OUT_RESERVE) {
402         error(ERR_WARNING, "attempt to initialise memory in"
403               " BSS section `%s': ignored", s->name);
404         if (type == OUT_REL2ADR)
405             realbytes = 2;
406         else if (type == OUT_REL4ADR)
407             realbytes = 4;
408         s->len += realbytes;
409         return;
410     }
411
412     if (type == OUT_RESERVE) {
413         if (s->type == SHT_PROGBITS) {
414             error(ERR_WARNING, "uninitialised space declared in"
415                   " non-BSS section `%s': zeroing", s->name);
416             elf_sect_write (s, NULL, realbytes);
417         } else
418             s->len += realbytes;
419     } else if (type == OUT_RAWDATA) {
420         if (segment != NO_SEG)
421             error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
422         elf_sect_write (s, data, realbytes);
423     } else if (type == OUT_ADDRESS) {
424         if (wrt != NO_SEG)
425             error(ERR_NONFATAL, "ELF format does not support WRT types");
426         if (segment != NO_SEG) {
427             if (segment % 2) {
428                 error(ERR_NONFATAL, "ELF format does not support"
429                       " segment base references");
430             } else
431                 elf_add_reloc (s, segment, FALSE);
432         }
433         p = mydata;
434         if (realbytes == 2 && segment != NO_SEG)
435             error (ERR_NONFATAL, "ELF format does not support 16-bit"
436                    " relocations");
437         WRITELONG (p, *(long *)data);
438         elf_sect_write (s, mydata, realbytes);
439     } else if (type == OUT_REL2ADR) {
440         error (ERR_NONFATAL, "ELF format does not support 16-bit"
441                " relocations");
442     } else if (type == OUT_REL4ADR) {
443         if (segment == segto)
444             error(ERR_PANIC, "intra-segment OUT_REL4ADR");
445         if (segment != NO_SEG && segment % 2) {
446             error(ERR_NONFATAL, "ELF format does not support"
447                   " segment base references");
448         } else
449             elf_add_reloc (s, segment, TRUE);
450         p = mydata;
451         WRITELONG (p, *(long*)data - realbytes);
452         elf_sect_write (s, mydata, 4L);
453     }
454 }
455
456 static void elf_write(void) {
457     int nsections, align;
458     char *p;
459     int commlen;
460     char comment[64];
461     int i;
462
463     struct SAA *symtab;
464     long symtablen, symtablocal;
465
466     /*
467      * Work out how many sections we will have. We have SHN_UNDEF,
468      * then the flexible user sections, then the four fixed
469      * sections `.comment', `.shstrtab', `.symtab' and `.strtab',
470      * then optionally relocation sections for the user sections.
471      */
472     nsections = 5;                     /* SHN_UNDEF and the fixed ones */
473     add_sectname ("", ".comment");
474     add_sectname ("", ".shstrtab");
475     add_sectname ("", ".symtab");
476     add_sectname ("", ".strtab");
477     for (i=0; i<nsects; i++) {
478         nsections++;                   /* for the section itself */
479         if (sects[i]->head) {
480             nsections++;               /* for its relocations */
481             add_sectname (".rel", sects[i]->name);
482         }
483     }
484
485     /*
486      * Do the comment.
487      */
488     *comment = '\0';
489     commlen = 2+sprintf(comment+1, "The Netwide Assembler %s", NASM_VER);
490
491     /*
492      * Output the ELF header.
493      */
494     fwrite ("\177ELF\1\1\1\0\0\0\0\0\0\0\0\0", 16, 1, elffp);
495     fwriteshort (1, elffp);            /* ET_REL relocatable file */
496     fwriteshort (3, elffp);            /* EM_386 processor ID */
497     fwritelong (1L, elffp);            /* EV_CURRENT file format version */
498     fwritelong (0L, elffp);            /* no entry point */
499     fwritelong (0L, elffp);            /* no program header table */
500     fwritelong (0x40L, elffp);         /* section headers straight after
501                                         * ELF header plus alignment */
502     fwritelong (0L, elffp);            /* 386 defines no special flags */
503     fwriteshort (0x34, elffp);         /* size of ELF header */
504     fwriteshort (0, elffp);            /* no program header table, again */
505     fwriteshort (0, elffp);            /* still no program header table */
506     fwriteshort (0x28, elffp);         /* size of section header */
507     fwriteshort (nsections, elffp);    /* number of sections */
508     fwriteshort (nsects+2, elffp);     /* string table section index for
509                                         * section header table */
510     fwritelong (0L, elffp);            /* align to 0x40 bytes */
511     fwritelong (0L, elffp);
512     fwritelong (0L, elffp);
513
514     /*
515      * Build the symbol table and relocation tables.
516      */
517     symtab = elf_build_symtab (&symtablen, &symtablocal);
518     for (i=0; i<nsects; i++)
519         if (sects[i]->head)
520             sects[i]->rel = elf_build_reltab (&sects[i]->rellen,
521                                               sects[i]->head);
522
523     /*
524      * Now output the section header table.
525      */
526
527     elf_foffs = 0x40 + 0x28 * nsections;
528     align = ((elf_foffs+SEG_ALIGN_1) & ~SEG_ALIGN_1) - elf_foffs;
529     elf_foffs += align;
530     elf_nsect = 0;
531
532     elf_section_header (0, 0, 0, NULL, FALSE, 0L, 0, 0, 0, 0); /* SHN_UNDEF */
533     p = shstrtab+1;
534     for (i=0; i<nsects; i++) {
535         elf_section_header (p - shstrtab, sects[i]->type, sects[i]->flags,
536                             (sects[i]->type == SHT_PROGBITS ?
537                              sects[i]->data : NULL), TRUE,
538                             sects[i]->len, 0, 0, sects[i]->align, 0);
539         p += strlen(p)+1;
540     }
541     elf_section_header (p - shstrtab, 1, 0, comment, FALSE,
542                         (long)commlen, 0, 0, 1, 0);/* .comment */
543     p += strlen(p)+1;
544     elf_section_header (p - shstrtab, 3, 0, shstrtab, FALSE,
545                         (long)shstrtablen, 0, 0, 1, 0);/* .shstrtab */
546     p += strlen(p)+1;
547     elf_section_header (p - shstrtab, 2, 0, symtab, TRUE,
548                         symtablen, nsects+4, symtablocal, 4, 16);/* .symtab */
549     p += strlen(p)+1;
550     elf_section_header (p - shstrtab, 3, 0, strs, TRUE,
551                         strslen, 0, 0, 1, 0);       /* .strtab */
552     for (i=0; i<nsects; i++) if (sects[i]->head) {
553         p += strlen(p)+1;
554         elf_section_header (p - shstrtab, 9, 0, sects[i]->rel, TRUE,
555                             sects[i]->rellen, nsects+3, i+1, 4, 8);
556     }
557
558     fwrite (align_str, align, 1, elffp);
559
560     /*
561      * Now output the sections.
562      */
563     elf_write_sections();
564
565     saa_free (symtab);
566 }
567
568 static struct SAA *elf_build_symtab (long *len, long *local) {
569     struct SAA *s = saa_init(1L);
570     struct Symbol *sym;
571     unsigned char entry[16], *p;
572     int i;
573
574     *len = *local = 0;
575
576     /*
577      * First, an all-zeros entry, required by the ELF spec.
578      */
579     saa_wbytes (s, NULL, 16L);         /* null symbol table entry */
580     *len += 16;
581     (*local)++;
582
583     /*
584      * Next, an entry for the file name.
585      */
586     p = entry;
587     WRITELONG (p, 1);                  /* we know it's 1st thing in strtab */
588     WRITELONG (p, 0);                  /* no value */
589     WRITELONG (p, 0);                  /* no size either */
590     WRITESHORT (p, 4);                 /* type FILE */
591     WRITESHORT (p, SHN_ABS);
592     saa_wbytes (s, entry, 16L);
593     *len += 16;
594     (*local)++;
595
596     /*
597      * Now some standard symbols defining the segments, for relocation
598      * purposes.
599      */
600     for (i = 1; i <= nsects+1; i++) {
601         p = entry;
602         WRITELONG (p, 0);              /* no symbol name */
603         WRITELONG (p, 0);              /* offset zero */
604         WRITELONG (p, 0);              /* size zero */
605         WRITESHORT (p, 3);             /* local section-type thing */
606         WRITESHORT (p, (i==1 ? SHN_ABS : i-1));   /* the section id */
607         saa_wbytes (s, entry, 16L);
608         *len += 16;
609         (*local)++;
610     }
611
612     /*
613      * Now the other local symbols.
614      */
615     saa_rewind (syms);
616     while ( (sym = saa_rstruct (syms)) ) {
617         if (sym->type == SYM_GLOBAL)
618             continue;
619         p = entry;
620         WRITELONG (p, sym->strpos);
621         WRITELONG (p, sym->value);
622         if (sym->section == SHN_COMMON)
623             WRITELONG (p, sym->value);
624         else
625             WRITELONG (p, 0);
626         WRITESHORT (p, 0);             /* local non-typed thing */
627         WRITESHORT (p, sym->section);
628         saa_wbytes (s, entry, 16L);
629         *len += 16;
630         (*local)++;
631     }
632
633     /*
634      * Now the global symbols.
635      */
636     saa_rewind (syms);
637     while ( (sym = saa_rstruct (syms)) ) {
638         if (sym->type != SYM_GLOBAL)
639             continue;
640         p = entry;
641         WRITELONG (p, sym->strpos);
642         WRITELONG (p, sym->value);
643         if (sym->section == SHN_COMMON)
644             WRITELONG (p, sym->value);
645         else
646             WRITELONG (p, 0);
647         WRITESHORT (p, SYM_GLOBAL);    /* global non-typed thing */
648         WRITESHORT (p, sym->section);
649         saa_wbytes (s, entry, 16L);
650         *len += 16;
651     }
652
653     return s;
654 }
655
656 static struct SAA *elf_build_reltab (long *len, struct Reloc *r) {
657     struct SAA *s;
658     unsigned char *p, entry[8];
659
660     if (!r)
661         return NULL;
662
663     s = saa_init(1L);
664     *len = 0;
665
666     while (r) {
667         long sym = r->symbol;
668
669         if (sym >= GLOBAL_TEMP_BASE)
670             sym += -GLOBAL_TEMP_BASE + (nsects+3) + nlocals;
671
672         p = entry;
673         WRITELONG (p, r->address);
674         WRITELONG (p, (sym << 8) + (r->relative ? 2 : 1));
675         saa_wbytes (s, entry, 8L);
676         *len += 8;
677
678         r = r->next;
679     }
680
681     return s;
682 }
683
684 static void elf_section_header (int name, int type, int flags,
685                                 void *data, int is_saa, long datalen,
686                                 int link, int info, int align, int eltsize) {
687     elf_sects[elf_nsect].data = data;
688     elf_sects[elf_nsect].len = datalen;
689     elf_sects[elf_nsect].is_saa = is_saa;
690     elf_nsect++;
691
692     fwritelong ((long)name, elffp);
693     fwritelong ((long)type, elffp);
694     fwritelong ((long)flags, elffp);
695     fwritelong (0L, elffp);            /* no address, ever, in object files */
696     fwritelong (type == 0 ? 0L : elf_foffs, elffp);
697     fwritelong (datalen, elffp);
698     if (data)
699         elf_foffs += (datalen+SEG_ALIGN_1) & ~SEG_ALIGN_1;
700     fwritelong ((long)link, elffp);
701     fwritelong ((long)info, elffp);
702     fwritelong ((long)align, elffp);
703     fwritelong ((long)eltsize, elffp);
704 }
705
706 static void elf_write_sections (void) {
707     int i;
708     for (i = 0; i < elf_nsect; i++)
709         if (elf_sects[i].data) {
710             long len = elf_sects[i].len;
711             long reallen = (len+SEG_ALIGN_1) & ~SEG_ALIGN_1;
712             long align = reallen - len;
713             if (elf_sects[i].is_saa)
714                 saa_fpwrite (elf_sects[i].data, elffp);
715             else
716                 fwrite (elf_sects[i].data, len, 1, elffp);
717             fwrite (align_str, align, 1, elffp);
718         }
719 }
720
721 static void elf_sect_write (struct Section *sect,
722                              unsigned char *data, unsigned long len) {
723     saa_wbytes (sect->data, data, len);
724     sect->len += len;
725 }
726
727 static long elf_segbase (long segment) {
728     return segment;
729 }
730
731 static int elf_directive (char *directive, char *value, int pass) {
732     return 0;
733 }
734
735 static void elf_filename (char *inname, char *outname, efunc error) {
736     strcpy(elf_module, inname);
737     standard_extension (inname, outname, ".o", error);
738 }
739
740 struct ofmt of_elf = {
741     "ELF32 (i386) object files (e.g. Linux)",
742     "elf",
743     elf_init,
744     elf_out,
745     elf_deflabel,
746     elf_section_names,
747     elf_segbase,
748     elf_directive,
749     elf_filename,
750     elf_cleanup
751 };
752
753 #endif /* OF_ELF */