a413c01b546e244fa39715c70fbcff50a323d86b
[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] == '.') {
294         return;
295     }
296
297     saa_wbytes (strs, name, (long)(1+strlen(name)));
298     strslen += 1+strlen(name);
299
300     sym = saa_wstruct (syms);
301
302     sym->strpos = pos;
303     sym->type = is_global ? SYM_GLOBAL : 0;
304     if (segment == NO_SEG)
305         sym->section = SHN_ABS;
306     else {
307         int i;
308         sym->section = SHN_UNDEF;
309         for (i=0; i<nsects; i++)
310             if (segment == sects[i]->index) {
311                 sym->section = i+1;
312                 break;
313             }
314     }
315
316     if (is_global == 2) {
317         sym->value = offset;
318         sym->section = SHN_COMMON;
319     } else
320         sym->value = (sym->section == SHN_UNDEF ? 0 : offset);
321
322     if (sym->type == SYM_GLOBAL) {
323         if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON)
324             bsym = raa_write (bsym, segment, nglobs);
325         nglobs++;
326     } else
327         nlocals++;
328 }
329
330 static void elf_add_reloc (struct Section *sect, long segment,
331                             int relative) {
332     struct Reloc *r;
333
334     r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
335     sect->tail = &r->next;
336     r->next = NULL;
337
338     r->address = sect->len;
339     if (segment == NO_SEG)
340         r->symbol = 2;
341     else {
342         int i;
343         r->symbol = 0;
344         for (i=0; i<nsects; i++)
345             if (segment == sects[i]->index)
346                 r->symbol = i+3;
347         if (!r->symbol)
348             r->symbol = GLOBAL_TEMP_BASE + raa_read(bsym, segment);
349     }
350     r->relative = relative;
351
352     sect->nrelocs++;
353 }
354
355 static void elf_out (long segto, void *data, unsigned long type,
356                       long segment, long wrt) {
357     struct Section *s;
358     long realbytes = type & OUT_SIZMASK;
359     unsigned char mydata[4], *p;
360     int i;
361
362     if (wrt != NO_SEG) {
363         wrt = NO_SEG;                  /* continue to do _something_ */
364         error (ERR_NONFATAL, "WRT not supported by ELF output format");
365     }
366
367     type &= OUT_TYPMASK;
368
369     /*
370      * handle absolute-assembly (structure definitions)
371      */
372     if (segto == NO_SEG) {
373         if (type != OUT_RESERVE)
374             error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
375                    " space");
376         return;
377     }
378
379     s = NULL;
380     for (i=0; i<nsects; i++)
381         if (segto == sects[i]->index) {
382             s = sects[i];
383             break;
384         }
385     if (!s) {
386         int tempint;                   /* ignored */
387         if (segto != elf_section_names (".text", 2, &tempint))
388             error (ERR_PANIC, "strange segment conditions in ELF driver");
389         else
390             s = sects[nsects-1];
391     }
392
393     if (s->type == SHT_NOBITS && type != OUT_RESERVE) {
394         error(ERR_WARNING, "attempt to initialise memory in"
395               " BSS section `%s': ignored", s->name);
396         if (type == OUT_REL2ADR)
397             realbytes = 2;
398         else if (type == OUT_REL4ADR)
399             realbytes = 4;
400         s->len += realbytes;
401         return;
402     }
403
404     if (type == OUT_RESERVE) {
405         if (s->type == SHT_PROGBITS) {
406             error(ERR_WARNING, "uninitialised space declared in"
407                   " non-BSS section `%s': zeroing", s->name);
408             elf_sect_write (s, NULL, realbytes);
409         } else
410             s->len += realbytes;
411     } else if (type == OUT_RAWDATA) {
412         if (segment != NO_SEG)
413             error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
414         elf_sect_write (s, data, realbytes);
415     } else if (type == OUT_ADDRESS) {
416         if (wrt != NO_SEG)
417             error(ERR_NONFATAL, "ELF format does not support WRT types");
418         if (segment != NO_SEG) {
419             if (segment % 2) {
420                 error(ERR_NONFATAL, "ELF format does not support"
421                       " segment base references");
422             } else
423                 elf_add_reloc (s, segment, FALSE);
424         }
425         p = mydata;
426         if (realbytes == 2 && segment != NO_SEG)
427             error (ERR_NONFATAL, "ELF format does not support 16-bit"
428                    " relocations");
429         WRITELONG (p, *(long *)data);
430         elf_sect_write (s, mydata, realbytes);
431     } else if (type == OUT_REL2ADR) {
432         error (ERR_NONFATAL, "ELF format does not support 16-bit"
433                " relocations");
434     } else if (type == OUT_REL4ADR) {
435         if (segment == segto)
436             error(ERR_PANIC, "intra-segment OUT_REL4ADR");
437         if (segment != NO_SEG && segment % 2) {
438             error(ERR_NONFATAL, "ELF format does not support"
439                   " segment base references");
440         } else
441             elf_add_reloc (s, segment, TRUE);
442         p = mydata;
443         WRITELONG (p, *(long*)data - realbytes);
444         elf_sect_write (s, mydata, 4L);
445     }
446 }
447
448 static void elf_write(void) {
449     int nsections, align;
450     char *p;
451     int commlen;
452     char comment[64];
453     int i;
454
455     struct SAA *symtab;
456     long symtablen, symtablocal;
457
458     /*
459      * Work out how many sections we will have. We have SHN_UNDEF,
460      * then the flexible user sections, then the four fixed
461      * sections `.comment', `.shstrtab', `.symtab' and `.strtab',
462      * then optionally relocation sections for the user sections.
463      */
464     nsections = 5;                     /* SHN_UNDEF and the fixed ones */
465     add_sectname ("", ".comment");
466     add_sectname ("", ".shstrtab");
467     add_sectname ("", ".symtab");
468     add_sectname ("", ".strtab");
469     for (i=0; i<nsects; i++) {
470         nsections++;                   /* for the section itself */
471         if (sects[i]->head) {
472             nsections++;               /* for its relocations */
473             add_sectname (".rel", sects[i]->name);
474         }
475     }
476
477     /*
478      * Do the comment.
479      */
480     *comment = '\0';
481     commlen = 2+sprintf(comment+1, "The Netwide Assembler %s", NASM_VER);
482
483     /*
484      * Output the ELF header.
485      */
486     fwrite ("\177ELF\1\1\1\0\0\0\0\0\0\0\0\0", 16, 1, elffp);
487     fwriteshort (1, elffp);            /* ET_REL relocatable file */
488     fwriteshort (3, elffp);            /* EM_386 processor ID */
489     fwritelong (1L, elffp);            /* EV_CURRENT file format version */
490     fwritelong (0L, elffp);            /* no entry point */
491     fwritelong (0L, elffp);            /* no program header table */
492     fwritelong (0x40L, elffp);         /* section headers straight after
493                                         * ELF header plus alignment */
494     fwritelong (0L, elffp);            /* 386 defines no special flags */
495     fwriteshort (0x34, elffp);         /* size of ELF header */
496     fwriteshort (0, elffp);            /* no program header table, again */
497     fwriteshort (0, elffp);            /* still no program header table */
498     fwriteshort (0x28, elffp);         /* size of section header */
499     fwriteshort (nsections, elffp);    /* number of sections */
500     fwriteshort (nsects+2, elffp);     /* string table section index for
501                                         * section header table */
502     fwritelong (0L, elffp);            /* align to 0x40 bytes */
503     fwritelong (0L, elffp);
504     fwritelong (0L, elffp);
505
506     /*
507      * Build the symbol table and relocation tables.
508      */
509     symtab = elf_build_symtab (&symtablen, &symtablocal);
510     for (i=0; i<nsects; i++)
511         if (sects[i]->head)
512             sects[i]->rel = elf_build_reltab (&sects[i]->rellen,
513                                               sects[i]->head);
514
515     /*
516      * Now output the section header table.
517      */
518
519     elf_foffs = 0x40 + 0x28 * nsections;
520     align = ((elf_foffs+SEG_ALIGN_1) & ~SEG_ALIGN_1) - elf_foffs;
521     elf_foffs += align;
522     elf_nsect = 0;
523
524     elf_section_header (0, 0, 0, NULL, FALSE, 0L, 0, 0, 0, 0); /* SHN_UNDEF */
525     p = shstrtab+1;
526     for (i=0; i<nsects; i++) {
527         elf_section_header (p - shstrtab, sects[i]->type, sects[i]->flags,
528                             (sects[i]->type == SHT_PROGBITS ?
529                              sects[i]->data : NULL), TRUE,
530                             sects[i]->len, 0, 0, sects[i]->align, 0);
531         p += strlen(p)+1;
532     }
533     elf_section_header (p - shstrtab, 1, 0, comment, FALSE,
534                         (long)commlen, 0, 0, 1, 0);/* .comment */
535     p += strlen(p)+1;
536     elf_section_header (p - shstrtab, 3, 0, shstrtab, FALSE,
537                         (long)shstrtablen, 0, 0, 1, 0);/* .shstrtab */
538     p += strlen(p)+1;
539     elf_section_header (p - shstrtab, 2, 0, symtab, TRUE,
540                         symtablen, nsects+4, symtablocal, 4, 16);/* .symtab */
541     p += strlen(p)+1;
542     elf_section_header (p - shstrtab, 3, 0, strs, TRUE,
543                         strslen, 0, 0, 1, 0);       /* .strtab */
544     for (i=0; i<nsects; i++) if (sects[i]->head) {
545         p += strlen(p)+1;
546         elf_section_header (p - shstrtab, 9, 0, sects[i]->rel, TRUE,
547                             sects[i]->rellen, nsects+3, i+1, 4, 8);
548     }
549
550     fwrite (align_str, align, 1, elffp);
551
552     /*
553      * Now output the sections.
554      */
555     elf_write_sections();
556
557     saa_free (symtab);
558 }
559
560 static struct SAA *elf_build_symtab (long *len, long *local) {
561     struct SAA *s = saa_init(1L);
562     struct Symbol *sym;
563     unsigned char entry[16], *p;
564     int i;
565
566     *len = *local = 0;
567
568     /*
569      * First, an all-zeros entry, required by the ELF spec.
570      */
571     saa_wbytes (s, NULL, 16L);         /* null symbol table entry */
572     *len += 16;
573     (*local)++;
574
575     /*
576      * Next, an entry for the file name.
577      */
578     p = entry;
579     WRITELONG (p, 1);                  /* we know it's 1st thing in strtab */
580     WRITELONG (p, 0);                  /* no value */
581     WRITELONG (p, 0);                  /* no size either */
582     WRITESHORT (p, 4);                 /* type FILE */
583     WRITESHORT (p, SHN_ABS);
584     saa_wbytes (s, entry, 16L);
585     *len += 16;
586     (*local)++;
587
588     /*
589      * Now some standard symbols defining the segments, for relocation
590      * purposes.
591      */
592     for (i = 1; i <= nsects+1; i++) {
593         p = entry;
594         WRITELONG (p, 0);              /* no symbol name */
595         WRITELONG (p, 0);              /* offset zero */
596         WRITELONG (p, 0);              /* size zero */
597         WRITESHORT (p, 3);             /* local section-type thing */
598         WRITESHORT (p, (i==1 ? SHN_ABS : i-1));   /* the section id */
599         saa_wbytes (s, entry, 16L);
600         *len += 16;
601         (*local)++;
602     }
603
604     /*
605      * Now the other local symbols.
606      */
607     saa_rewind (syms);
608     while ( (sym = saa_rstruct (syms)) ) {
609         if (sym->type == SYM_GLOBAL)
610             continue;
611         p = entry;
612         WRITELONG (p, sym->strpos);
613         WRITELONG (p, sym->value);
614         if (sym->section == SHN_COMMON)
615             WRITELONG (p, sym->value);
616         else
617             WRITELONG (p, 0);
618         WRITESHORT (p, 0);             /* local non-typed thing */
619         WRITESHORT (p, sym->section);
620         saa_wbytes (s, entry, 16L);
621         *len += 16;
622         (*local)++;
623     }
624
625     /*
626      * Now the global symbols.
627      */
628     saa_rewind (syms);
629     while ( (sym = saa_rstruct (syms)) ) {
630         if (sym->type != SYM_GLOBAL)
631             continue;
632         p = entry;
633         WRITELONG (p, sym->strpos);
634         WRITELONG (p, sym->value);
635         if (sym->section == SHN_COMMON)
636             WRITELONG (p, sym->value);
637         else
638             WRITELONG (p, 0);
639         WRITESHORT (p, SYM_GLOBAL);    /* global non-typed thing */
640         WRITESHORT (p, sym->section);
641         saa_wbytes (s, entry, 16L);
642         *len += 16;
643     }
644
645     return s;
646 }
647
648 static struct SAA *elf_build_reltab (long *len, struct Reloc *r) {
649     struct SAA *s;
650     unsigned char *p, entry[8];
651
652     if (!r)
653         return NULL;
654
655     s = saa_init(1L);
656     *len = 0;
657
658     while (r) {
659         long sym = r->symbol;
660
661         if (sym >= GLOBAL_TEMP_BASE)
662             sym += -GLOBAL_TEMP_BASE + (nsects+3) + nlocals;
663
664         p = entry;
665         WRITELONG (p, r->address);
666         WRITELONG (p, (sym << 8) + (r->relative ? 2 : 1));
667         saa_wbytes (s, entry, 8L);
668         *len += 8;
669
670         r = r->next;
671     }
672
673     return s;
674 }
675
676 static void elf_section_header (int name, int type, int flags,
677                                 void *data, int is_saa, long datalen,
678                                 int link, int info, int align, int eltsize) {
679     elf_sects[elf_nsect].data = data;
680     elf_sects[elf_nsect].len = datalen;
681     elf_sects[elf_nsect].is_saa = is_saa;
682     elf_nsect++;
683
684     fwritelong ((long)name, elffp);
685     fwritelong ((long)type, elffp);
686     fwritelong ((long)flags, elffp);
687     fwritelong (0L, elffp);            /* no address, ever, in object files */
688     fwritelong (type == 0 ? 0L : elf_foffs, elffp);
689     fwritelong (datalen, elffp);
690     if (data)
691         elf_foffs += (datalen+SEG_ALIGN_1) & ~SEG_ALIGN_1;
692     fwritelong ((long)link, elffp);
693     fwritelong ((long)info, elffp);
694     fwritelong ((long)align, elffp);
695     fwritelong ((long)eltsize, elffp);
696 }
697
698 static void elf_write_sections (void) {
699     int i;
700     for (i = 0; i < elf_nsect; i++)
701         if (elf_sects[i].data) {
702             long len = elf_sects[i].len;
703             long reallen = (len+SEG_ALIGN_1) & ~SEG_ALIGN_1;
704             long align = reallen - len;
705             if (elf_sects[i].is_saa)
706                 saa_fpwrite (elf_sects[i].data, elffp);
707             else
708                 fwrite (elf_sects[i].data, len, 1, elffp);
709             fwrite (align_str, align, 1, elffp);
710         }
711 }
712
713 static void elf_sect_write (struct Section *sect,
714                              unsigned char *data, unsigned long len) {
715     saa_wbytes (sect->data, data, len);
716     sect->len += len;
717 }
718
719 static long elf_segbase (long segment) {
720     return segment;
721 }
722
723 static int elf_directive (char *directive, char *value, int pass) {
724     return 0;
725 }
726
727 static void elf_filename (char *inname, char *outname, efunc error) {
728     strcpy(elf_module, inname);
729     standard_extension (inname, outname, ".o", error);
730 }
731
732 struct ofmt of_elf = {
733     "ELF32 (i386) object files (e.g. Linux)",
734     "elf",
735     elf_init,
736     elf_out,
737     elf_deflabel,
738     elf_section_names,
739     elf_segbase,
740     elf_directive,
741     elf_filename,
742     elf_cleanup
743 };
744
745 #endif /* OF_ELF */