1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 1996-2017 The NASM Authors - All Rights Reserved
4  *   See the file AUTHORS included with the NASM distribution for
5  *   the specific copyright holders.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following
9  *   conditions are met:
10  *
11  *   * Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *   * Redistributions in binary form must reproduce the above
14  *     copyright notice, this list of conditions and the following
15  *     disclaimer in the documentation and/or other materials provided
16  *     with the distribution.
17  *
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * ----------------------------------------------------------------------- */
33 
34 /*
35  * Common code for outelf32 and outelf64
36  */
37 
38 #include "compiler.h"
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 
43 #include "nasm.h"
44 #include "nasmlib.h"
45 #include "error.h"
46 #include "saa.h"
47 #include "raa.h"
48 #include "stdscan.h"
49 #include "eval.h"
50 #include "outform.h"
51 #include "outlib.h"
52 #include "rbtree.h"
53 #include "ver.h"
54 
55 #include "dwarf.h"
56 #include "stabs.h"
57 #include "outelf.h"
58 #include "elf.h"
59 
60 #if defined(OF_ELF32) || defined(OF_ELF64) || defined(OF_ELFX32)
61 
62 #define SECT_DELTA 32
63 static struct elf_section **sects;
64 static int nsects, sectlen;
65 
66 #define SHSTR_DELTA 256
67 static char *shstrtab;
68 static int shstrtablen, shstrtabsize;
69 
70 static struct SAA *syms;
71 static uint32_t nlocals, nglobs, ndebugs; /* Symbol counts */
72 
73 static int32_t def_seg;
74 
75 static struct RAA *bsym;
76 
77 static struct SAA *strs;
78 static uint32_t strslen;
79 
80 static struct elf_symbol *fwds;
81 
82 static char elf_module[FILENAME_MAX];
83 
84 extern const struct ofmt of_elf32;
85 extern const struct ofmt of_elf64;
86 extern const struct ofmt of_elfx32;
87 
88 static struct ELF_SECTDATA {
89     void                *data;
90     int64_t             len;
91     bool                is_saa;
92 } *elf_sects;
93 
94 static int elf_nsect, nsections;
95 static int64_t elf_foffs;
96 
97 static void elf_write(void);
98 static void elf_sect_write(struct elf_section *, const void *, size_t);
99 static void elf_sect_writeaddr(struct elf_section *, int64_t, size_t);
100 static void elf_section_header(int, int, uint64_t, void *, bool, uint64_t, int, int,
101                                int, int);
102 static void elf_write_sections(void);
103 static struct SAA *elf_build_symtab(int32_t *, int32_t *);
104 static struct SAA *elf_build_reltab(uint64_t *, struct elf_reloc *);
105 static void add_sectname(const char *, const char *);
106 
107 struct erel {
108     int                 offset;
109     int                 info;
110 };
111 
112 struct symlininfo {
113     int                 offset;
114     int                 section;        /* index into sects[] */
115     int                 segto;          /* internal section number */
116     char                *name;          /* shallow-copied pointer of section name */
117 };
118 
119 struct linelist {
120     struct linelist     *next;
121     struct linelist     *last;
122     struct symlininfo   info;
123     char                *filename;
124     int                 line;
125 };
126 
127 struct sectlist {
128     struct SAA          *psaa;
129     int                 section;
130     int                 line;
131     int                 offset;
132     int                 file;
133     struct sectlist     *next;
134     struct sectlist     *last;
135 };
136 
137 /* common debug variables */
138 static int currentline = 1;
139 static int debug_immcall = 0;
140 
141 /* stabs debug variables */
142 static struct linelist *stabslines = 0;
143 static int numlinestabs = 0;
144 static char *stabs_filename = 0;
145 static uint8_t *stabbuf = 0, *stabstrbuf = 0, *stabrelbuf = 0;
146 static int stablen, stabstrlen, stabrellen;
147 
148 /* dwarf debug variables */
149 static struct linelist *dwarf_flist = 0, *dwarf_clist = 0, *dwarf_elist = 0;
150 static struct sectlist *dwarf_fsect = 0, *dwarf_csect = 0, *dwarf_esect = 0;
151 static int dwarf_numfiles = 0, dwarf_nsections;
152 static uint8_t *arangesbuf = 0, *arangesrelbuf = 0, *pubnamesbuf = 0, *infobuf = 0,  *inforelbuf = 0,
153                *abbrevbuf = 0, *linebuf = 0, *linerelbuf = 0, *framebuf = 0, *locbuf = 0;
154 static int8_t line_base = -5, line_range = 14, opcode_base = 13;
155 static int arangeslen, arangesrellen, pubnameslen, infolen, inforellen,
156            abbrevlen, linelen, linerellen, framelen, loclen;
157 static int64_t dwarf_infosym, dwarf_abbrevsym, dwarf_linesym;
158 
159 static struct elf_symbol *lastsym;
160 
161 /* common debugging routines */
162 static void debug_typevalue(int32_t);
163 
164 /* stabs debugging routines */
165 static void stabs_linenum(const char *filename, int32_t linenumber, int32_t);
166 static void stabs_output(int, void *);
167 static void stabs_generate(void);
168 static void stabs_cleanup(void);
169 
170 /* dwarf debugging routines */
171 static void dwarf_init(void);
172 static void dwarf_linenum(const char *filename, int32_t linenumber, int32_t);
173 static void dwarf_output(int, void *);
174 static void dwarf_generate(void);
175 static void dwarf_cleanup(void);
176 static void dwarf_findfile(const char *);
177 static void dwarf_findsect(const int);
178 
179 static bool is_elf64(void);
180 static bool is_elf32(void);
181 static bool is_elfx32(void);
182 
183 static bool dfmt_is_stabs(void);
184 static bool dfmt_is_dwarf(void);
185 
186 /*
187  * Special NASM section numbers which are used to define ELF special
188  * symbols.
189  */
190 static int32_t elf_gotpc_sect, elf_gotoff_sect;
191 static int32_t elf_got_sect, elf_plt_sect;
192 static int32_t elf_sym_sect, elf_gottpoff_sect, elf_tlsie_sect;
193 
194 uint8_t elf_osabi = 0;      /* Default OSABI = 0 (System V or Linux) */
195 uint8_t elf_abiver = 0;     /* Current ABI version */
196 
197 const struct elf_known_section elf_known_sections[] = {
198     { ".text",    SHT_PROGBITS, SHF_ALLOC|SHF_EXECINSTR,     16 },
199     { ".rodata",  SHT_PROGBITS, SHF_ALLOC,                    4 },
200     { ".lrodata", SHT_PROGBITS, SHF_ALLOC,                    4 },
201     { ".data",    SHT_PROGBITS, SHF_ALLOC|SHF_WRITE,          4 },
202     { ".ldata",   SHT_PROGBITS, SHF_ALLOC|SHF_WRITE,          4 },
203     { ".bss",     SHT_NOBITS,   SHF_ALLOC|SHF_WRITE,          4 },
204     { ".lbss",    SHT_NOBITS,   SHF_ALLOC|SHF_WRITE,          4 },
205     { ".tdata",   SHT_PROGBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS,  4 },
206     { ".tbss",    SHT_NOBITS,   SHF_ALLOC|SHF_WRITE|SHF_TLS,  4 },
207     { ".comment", SHT_PROGBITS, 0,                            1 },
208     { NULL,       SHT_PROGBITS, SHF_ALLOC,                    1 } /* default */
209 };
210 
211 /* parse section attributes */
elf_section_attrib(char * name,char * attr,int pass,uint32_t * flags_and,uint32_t * flags_or,uint64_t * align,int * type)212 static void elf_section_attrib(char *name, char *attr, int pass,
213                                uint32_t *flags_and, uint32_t *flags_or,
214                                uint64_t *align, int *type)
215 {
216     char *opt, *val, *next;
217 
218     opt = nasm_skip_spaces(attr);
219     if (!opt || !*opt)
220         return;
221 
222     while ((opt = nasm_opt_val(opt, &val, &next))) {
223         if (!nasm_stricmp(opt, "align")) {
224             if (!val) {
225                 nasm_error(ERR_NONFATAL,
226                            "section align without value specified");
227             } else {
228                 *align = atoi(val);
229                 if (*align == 0) {
230                     *align = SHA_ANY;
231                 } else if (!is_power2(*align)) {
232                     nasm_error(ERR_NONFATAL,
233                                "section alignment %"PRId64" is not a power of two",
234                                *align);
235                     *align = SHA_ANY;
236                 }
237             }
238         } else if (!nasm_stricmp(opt, "alloc")) {
239             *flags_and  |= SHF_ALLOC;
240             *flags_or   |= SHF_ALLOC;
241         } else if (!nasm_stricmp(opt, "noalloc")) {
242             *flags_and  |= SHF_ALLOC;
243             *flags_or   &= ~SHF_ALLOC;
244         } else if (!nasm_stricmp(opt, "exec")) {
245             *flags_and  |= SHF_EXECINSTR;
246             *flags_or   |= SHF_EXECINSTR;
247         } else if (!nasm_stricmp(opt, "noexec")) {
248             *flags_and  |= SHF_EXECINSTR;
249             *flags_or   &= ~SHF_EXECINSTR;
250         } else if (!nasm_stricmp(opt, "write")) {
251             *flags_and  |= SHF_WRITE;
252             *flags_or   |= SHF_WRITE;
253         } else if (!nasm_stricmp(opt, "tls")) {
254             *flags_and  |= SHF_TLS;
255             *flags_or   |= SHF_TLS;
256         } else if (!nasm_stricmp(opt, "nowrite")) {
257             *flags_and  |= SHF_WRITE;
258             *flags_or   &= ~SHF_WRITE;
259         } else if (!nasm_stricmp(opt, "progbits")) {
260             *type = SHT_PROGBITS;
261         } else if (!nasm_stricmp(opt, "nobits")) {
262             *type = SHT_NOBITS;
263         } else if (pass == 1) {
264             nasm_error(ERR_WARNING,
265                        "Unknown section attribute '%s' ignored on"
266                        " declaration of section `%s'", opt, name);
267         }
268         opt = next;
269     }
270 }
271 
272 static enum directive_result
elf_directive(enum directive directive,char * value,int pass)273 elf_directive(enum directive directive, char *value, int pass)
274 {
275     int64_t n;
276     bool err;
277     char *p;
278 
279     switch (directive) {
280     case D_OSABI:
281         if (pass == 2)
282             return DIRR_OK; /* ignore in pass 2 */
283 
284         n = readnum(value, &err);
285         if (err) {
286             nasm_error(ERR_NONFATAL, "`osabi' directive requires a parameter");
287             return DIRR_ERROR;
288         }
289 
290         if (n < 0 || n > 255) {
291             nasm_error(ERR_NONFATAL, "valid osabi numbers are 0 to 255");
292             return DIRR_ERROR;
293         }
294 
295         elf_osabi  = n;
296         elf_abiver = 0;
297 
298         p = strchr(value,',');
299         if (!p)
300             return DIRR_OK;
301 
302         n = readnum(p + 1, &err);
303         if (err || n < 0 || n > 255) {
304             nasm_error(ERR_NONFATAL, "invalid ABI version number (valid: 0 to 255)");
305             return DIRR_ERROR;
306         }
307 
308         elf_abiver = n;
309         return DIRR_OK;
310 
311     default:
312         return DIRR_UNKNOWN;
313     }
314 }
315 
elf_init(void)316 static void elf_init(void)
317 {
318     strlcpy(elf_module, inname, sizeof(elf_module));
319     sects = NULL;
320     nsects = sectlen = 0;
321     syms = saa_init((int32_t)sizeof(struct elf_symbol));
322     nlocals = nglobs = ndebugs = 0;
323     bsym = raa_init();
324     strs = saa_init(1L);
325     saa_wbytes(strs, "\0", 1L);
326     saa_wbytes(strs, elf_module, strlen(elf_module)+1);
327     strslen = 2 + strlen(elf_module);
328     shstrtab = NULL;
329     shstrtablen = shstrtabsize = 0;;
330     add_sectname("", "");
331 
332     fwds = NULL;
333 
334     /*
335      * FIXME: tlsie is Elf32 only and
336      * gottpoff is Elfx32|64 only.
337      */
338 
339     elf_gotpc_sect = seg_alloc();
340     backend_label("..gotpc", elf_gotpc_sect + 1, 0L);
341     elf_gotoff_sect = seg_alloc();
342     backend_label("..gotoff", elf_gotoff_sect + 1, 0L);
343     elf_got_sect = seg_alloc();
344     backend_label("..got", elf_got_sect + 1, 0L);
345     elf_plt_sect = seg_alloc();
346     backend_label("..plt", elf_plt_sect + 1, 0L);
347     elf_sym_sect = seg_alloc();
348     backend_label("..sym", elf_sym_sect + 1, 0L);
349     elf_gottpoff_sect = seg_alloc();
350     backend_label("..gottpoff", elf_gottpoff_sect + 1, 0L);
351     elf_tlsie_sect = seg_alloc();
352     backend_label("..tlsie", elf_tlsie_sect + 1, 0L);
353 
354     def_seg = seg_alloc();
355 }
356 
elf_cleanup(void)357 static void elf_cleanup(void)
358 {
359     struct elf_reloc *r;
360     int i;
361 
362     elf_write();
363     for (i = 0; i < nsects; i++) {
364         if (sects[i]->type != SHT_NOBITS)
365             saa_free(sects[i]->data);
366         if (sects[i]->head)
367             saa_free(sects[i]->rel);
368         while (sects[i]->head) {
369             r = sects[i]->head;
370             sects[i]->head = sects[i]->head->next;
371             nasm_free(r);
372         }
373     }
374     nasm_free(sects);
375     saa_free(syms);
376     raa_free(bsym);
377     saa_free(strs);
378     dfmt->cleanup();
379 }
380 
381 /* add entry to the elf .shstrtab section */
add_sectname(const char * firsthalf,const char * secondhalf)382 static void add_sectname(const char *firsthalf, const char *secondhalf)
383 {
384     int len = strlen(firsthalf) + strlen(secondhalf);
385     while (shstrtablen + len + 1 > shstrtabsize)
386         shstrtab = nasm_realloc(shstrtab, (shstrtabsize += SHSTR_DELTA));
387     strcpy(shstrtab + shstrtablen, firsthalf);
388     strcat(shstrtab + shstrtablen, secondhalf);
389     shstrtablen += len + 1;
390 }
391 
elf_make_section(char * name,int type,int flags,int align)392 static int elf_make_section(char *name, int type, int flags, int align)
393 {
394     struct elf_section *s;
395 
396     s = nasm_zalloc(sizeof(*s));
397 
398     if (type != SHT_NOBITS)
399         s->data = saa_init(1L);
400     s->tail = &s->head;
401     if (!strcmp(name, ".text"))
402         s->index = def_seg;
403     else
404         s->index = seg_alloc();
405     add_sectname("", name);
406 
407     s->name     = nasm_strdup(name);
408     s->type     = type;
409     s->flags    = flags;
410     s->align    = align;
411 
412     if (nsects >= sectlen)
413         sects = nasm_realloc(sects, (sectlen += SECT_DELTA) * sizeof(*sects));
414     sects[nsects++] = s;
415 
416     return nsects - 1;
417 }
418 
elf_section_names(char * name,int pass,int * bits)419 static int32_t elf_section_names(char *name, int pass, int *bits)
420 {
421     char *p;
422     uint32_t flags, flags_and, flags_or;
423     uint64_t align;
424     int type, i;
425 
426     if (!name) {
427         *bits = ofmt->maxbits;
428         return def_seg;
429     }
430 
431     p = nasm_skip_word(name);
432     if (*p)
433         *p++ = '\0';
434     flags_and = flags_or = type = align = 0;
435 
436     elf_section_attrib(name, p, pass, &flags_and,
437                        &flags_or, &align, &type);
438 
439     if (!strcmp(name, ".shstrtab") ||
440         !strcmp(name, ".symtab") ||
441         !strcmp(name, ".strtab")) {
442         nasm_error(ERR_NONFATAL, "attempt to redefine reserved section"
443               "name `%s'", name);
444         return NO_SEG;
445     }
446 
447     for (i = 0; i < nsects; i++)
448         if (!strcmp(name, sects[i]->name))
449             break;
450     if (i == nsects) {
451         const struct elf_known_section *ks = elf_known_sections;
452 
453         while (ks->name) {
454             if (!strcmp(name, ks->name))
455                 break;
456             ks++;
457         }
458 
459         type = type ? type : ks->type;
460         align = align ? align : ks->align;
461         flags = (ks->flags & ~flags_and) | flags_or;
462 
463         i = elf_make_section(name, type, flags, align);
464     } else if (pass == 1) {
465           if ((type && sects[i]->type != type)
466               || (align && sects[i]->align != align)
467               || (flags_and && ((sects[i]->flags & flags_and) != flags_or)))
468             nasm_error(ERR_WARNING, "incompatible section attributes ignored on"
469                   " redeclaration of section `%s'", name);
470     }
471 
472     return sects[i]->index;
473 }
474 
elf_deflabel(char * name,int32_t segment,int64_t offset,int is_global,char * special)475 static void elf_deflabel(char *name, int32_t segment, int64_t offset,
476                          int is_global, char *special)
477 {
478     int pos = strslen;
479     struct elf_symbol *sym;
480     bool special_used = false;
481 
482 #if defined(DEBUG) && DEBUG>2
483     nasm_error(ERR_DEBUG,
484             " elf_deflabel: %s, seg=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
485             name, segment, offset, is_global, special);
486 #endif
487     if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
488         /*
489          * This is a NASM special symbol. We never allow it into
490          * the ELF symbol table, even if it's a valid one. If it
491          * _isn't_ a valid one, we should barf immediately.
492          *
493          * FIXME: tlsie is Elf32 only, and gottpoff is Elfx32|64 only.
494          */
495         if (strcmp(name, "..gotpc") && strcmp(name, "..gotoff") &&
496             strcmp(name, "..got") && strcmp(name, "..plt") &&
497             strcmp(name, "..sym") && strcmp(name, "..gottpoff") &&
498             strcmp(name, "..tlsie"))
499             nasm_error(ERR_NONFATAL, "unrecognised special symbol `%s'", name);
500         return;
501     }
502 
503     if (is_global == 3) {
504         struct elf_symbol **s;
505         /*
506          * Fix up a forward-reference symbol size from the first
507          * pass.
508          */
509         for (s = &fwds; *s; s = &(*s)->nextfwd)
510             if (!strcmp((*s)->name, name)) {
511                 struct tokenval tokval;
512                 expr *e;
513                 char *p = nasm_skip_spaces(nasm_skip_word(special));
514 
515                 stdscan_reset();
516                 stdscan_set(p);
517                 tokval.t_type = TOKEN_INVALID;
518                 e = evaluate(stdscan, NULL, &tokval, NULL, 1, NULL);
519                 if (e) {
520                     if (!is_simple(e))
521                         nasm_error(ERR_NONFATAL, "cannot use relocatable"
522                               " expression as symbol size");
523                     else
524                         (*s)->size = reloc_value(e);
525                 }
526 
527                 /*
528                  * Remove it from the list of unresolved sizes.
529                  */
530                 nasm_free((*s)->name);
531                 *s = (*s)->nextfwd;
532                 return;
533             }
534         return;                 /* it wasn't an important one */
535     }
536 
537     saa_wbytes(strs, name, (int32_t)(1 + strlen(name)));
538     strslen += 1 + strlen(name);
539 
540     lastsym = sym = saa_wstruct(syms);
541 
542     memset(&sym->symv, 0, sizeof(struct rbtree));
543 
544     sym->strpos = pos;
545     sym->type = is_global ? SYM_GLOBAL : SYM_LOCAL;
546     sym->other = STV_DEFAULT;
547     sym->size = 0;
548     if (segment == NO_SEG)
549         sym->section = SHN_ABS;
550     else {
551         int i;
552         sym->section = SHN_UNDEF;
553         if (segment == def_seg) {
554             /* we have to be sure at least text section is there */
555             int tempint;
556             if (segment != elf_section_names(".text", 2, &tempint))
557                 nasm_panic("strange segment conditions in ELF driver");
558         }
559         for (i = 0; i < nsects; i++) {
560             if (segment == sects[i]->index) {
561                 sym->section = i + 1;
562                 break;
563             }
564         }
565     }
566 
567     if (is_global == 2) {
568         sym->size = offset;
569         sym->symv.key = 0;
570         sym->section = SHN_COMMON;
571         /*
572          * We have a common variable. Check the special text to see
573          * if it's a valid number and power of two; if so, store it
574          * as the alignment for the common variable.
575          */
576         if (special) {
577             bool err;
578             sym->symv.key = readnum(special, &err);
579             if (err)
580                 nasm_error(ERR_NONFATAL, "alignment constraint `%s' is not a"
581                       " valid number", special);
582             else if ((sym->symv.key | (sym->symv.key - 1)) != 2 * sym->symv.key - 1)
583                 nasm_error(ERR_NONFATAL, "alignment constraint `%s' is not a"
584                       " power of two", special);
585         }
586         special_used = true;
587     } else
588         sym->symv.key = (sym->section == SHN_UNDEF ? 0 : offset);
589 
590     if (sym->type == SYM_GLOBAL) {
591         /*
592          * If sym->section == SHN_ABS, then the first line of the
593          * else section would cause a core dump, because its a reference
594          * beyond the end of the section array.
595          * This behaviour is exhibited by this code:
596          *     GLOBAL crash_nasm
597          *     crash_nasm equ 0
598          * To avoid such a crash, such requests are silently discarded.
599          * This may not be the best solution.
600          */
601         if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON) {
602             bsym = raa_write(bsym, segment, nglobs);
603         } else if (sym->section != SHN_ABS) {
604             /*
605              * This is a global symbol; so we must add it to the rbtree
606              * of global symbols in its section.
607              *
608              * In addition, we check the special text for symbol
609              * type and size information.
610              */
611             sects[sym->section-1]->gsyms =
612                 rb_insert(sects[sym->section-1]->gsyms, &sym->symv);
613 
614             if (special) {
615                 int n = strcspn(special, " \t");
616 
617                 if (!nasm_strnicmp(special, "function", n))
618                     sym->type |= STT_FUNC;
619                 else if (!nasm_strnicmp(special, "data", n) ||
620                          !nasm_strnicmp(special, "object", n))
621                     sym->type |= STT_OBJECT;
622                 else if (!nasm_strnicmp(special, "notype", n))
623                     sym->type |= STT_NOTYPE;
624                 else
625                     nasm_error(ERR_NONFATAL, "unrecognised symbol type `%.*s'",
626                           n, special);
627                 special += n;
628 
629                 special = nasm_skip_spaces(special);
630                 if (*special) {
631                     n = strcspn(special, " \t");
632                     if (!nasm_strnicmp(special, "default", n))
633                         sym->other = STV_DEFAULT;
634                     else if (!nasm_strnicmp(special, "internal", n))
635                         sym->other = STV_INTERNAL;
636                     else if (!nasm_strnicmp(special, "hidden", n))
637                         sym->other = STV_HIDDEN;
638                     else if (!nasm_strnicmp(special, "protected", n))
639                         sym->other = STV_PROTECTED;
640                     else
641                         n = 0;
642                     special += n;
643                 }
644 
645                 if (*special) {
646                     struct tokenval tokval;
647                     expr *e;
648                     int fwd = 0;
649                     char *saveme = stdscan_get();
650 
651                     while (special[n] && nasm_isspace(special[n]))
652                         n++;
653                     /*
654                      * We have a size expression; attempt to
655                      * evaluate it.
656                      */
657                     stdscan_reset();
658                     stdscan_set(special + n);
659                     tokval.t_type = TOKEN_INVALID;
660                     e = evaluate(stdscan, NULL, &tokval, &fwd, 0, NULL);
661                     if (fwd) {
662                         sym->nextfwd = fwds;
663                         fwds = sym;
664                         sym->name = nasm_strdup(name);
665                     } else if (e) {
666                         if (!is_simple(e))
667                             nasm_error(ERR_NONFATAL, "cannot use relocatable"
668                                   " expression as symbol size");
669                         else
670                             sym->size = reloc_value(e);
671                     }
672                     stdscan_set(saveme);
673                 }
674                 special_used = true;
675             }
676             /*
677              * If TLS segment, mark symbol accordingly.
678              */
679             if (sects[sym->section - 1]->flags & SHF_TLS) {
680                 sym->type &= 0xf0;
681                 sym->type |= STT_TLS;
682             }
683         }
684         sym->globnum = nglobs;
685         nglobs++;
686     } else
687         nlocals++;
688 
689     if (special && !special_used)
690         nasm_error(ERR_NONFATAL, "no special symbol features supported here");
691 }
692 
elf_add_reloc(struct elf_section * sect,int32_t segment,int64_t offset,int type)693 static void elf_add_reloc(struct elf_section *sect, int32_t segment,
694                           int64_t offset, int type)
695 {
696     struct elf_reloc *r;
697 
698     r = *sect->tail = nasm_zalloc(sizeof(struct elf_reloc));
699     sect->tail = &r->next;
700 
701     r->address = sect->len;
702     r->offset = offset;
703 
704     if (segment != NO_SEG) {
705         int i;
706         for (i = 0; i < nsects; i++)
707             if (segment == sects[i]->index)
708                 r->symbol = i + 2;
709         if (!r->symbol)
710             r->symbol = GLOBAL_TEMP_BASE + raa_read(bsym, segment);
711     }
712     r->type = type;
713 
714     sect->nrelocs++;
715 }
716 
717 /*
718  * This routine deals with ..got and ..sym relocations: the more
719  * complicated kinds. In shared-library writing, some relocations
720  * with respect to global symbols must refer to the precise symbol
721  * rather than referring to an offset from the base of the section
722  * _containing_ the symbol. Such relocations call to this routine,
723  * which searches the symbol list for the symbol in question.
724  *
725  * R_386_GOT32 | R_X86_64_GOT32 references require the _exact_ symbol address to be
726  * used; R_386_32 | R_X86_64_32 references can be at an offset from the symbol.
727  * The boolean argument `exact' tells us this.
728  *
729  * Return value is the adjusted value of `addr', having become an
730  * offset from the symbol rather than the section. Should always be
731  * zero when returning from an exact call.
732  *
733  * Limitation: if you define two symbols at the same place,
734  * confusion will occur.
735  *
736  * Inefficiency: we search, currently, using a linked list which
737  * isn't even necessarily sorted.
738  */
elf_add_gsym_reloc(struct elf_section * sect,int32_t segment,uint64_t offset,int64_t pcrel,int type,bool exact)739 static int64_t elf_add_gsym_reloc(struct elf_section *sect,
740                                   int32_t segment, uint64_t offset,
741                                   int64_t pcrel, int type, bool exact)
742 {
743     struct elf_reloc *r;
744     struct elf_section *s;
745     struct elf_symbol *sym;
746     struct rbtree *srb;
747     int i;
748 
749     /*
750      * First look up the segment/offset pair and find a global
751      * symbol corresponding to it. If it's not one of our segments,
752      * then it must be an external symbol, in which case we're fine
753      * doing a normal elf_add_reloc after first sanity-checking
754      * that the offset from the symbol is zero.
755      */
756     s = NULL;
757     for (i = 0; i < nsects; i++)
758         if (segment == sects[i]->index) {
759             s = sects[i];
760             break;
761         }
762 
763     if (!s) {
764         if (exact && offset)
765             nasm_error(ERR_NONFATAL, "invalid access to an external symbol");
766         else
767             elf_add_reloc(sect, segment, offset - pcrel, type);
768         return 0;
769     }
770 
771     srb = rb_search(s->gsyms, offset);
772     if (!srb || (exact && srb->key != offset)) {
773         nasm_error(ERR_NONFATAL, "unable to find a suitable global symbol"
774                     " for this reference");
775         return 0;
776     }
777     sym = container_of(srb, struct elf_symbol, symv);
778 
779     r = *sect->tail = nasm_malloc(sizeof(struct elf_reloc));
780     sect->tail = &r->next;
781 
782     r->next     = NULL;
783     r->address  = sect->len;
784     r->offset = offset - pcrel - sym->symv.key;
785     r->symbol   = GLOBAL_TEMP_BASE + sym->globnum;
786     r->type     = type;
787 
788     sect->nrelocs++;
789     return r->offset;
790 }
791 
elf32_out(int32_t segto,const void * data,enum out_type type,uint64_t size,int32_t segment,int32_t wrt)792 static void elf32_out(int32_t segto, const void *data,
793                       enum out_type type, uint64_t size,
794                       int32_t segment, int32_t wrt)
795 {
796     struct elf_section *s;
797     int64_t addr;
798     int reltype, bytes;
799     int i;
800     static struct symlininfo sinfo;
801 
802     s = NULL;
803     for (i = 0; i < nsects; i++)
804         if (segto == sects[i]->index) {
805             s = sects[i];
806             break;
807         }
808     if (!s) {
809         int tempint;            /* ignored */
810         if (segto != elf_section_names(".text", 2, &tempint))
811             nasm_panic("strange segment conditions in ELF driver");
812         else {
813             s = sects[nsects - 1];
814             i = nsects - 1;
815         }
816     }
817 
818     /* again some stabs debugging stuff */
819     sinfo.offset = s->len;
820     sinfo.section = i;
821     sinfo.segto = segto;
822     sinfo.name = s->name;
823     dfmt->debug_output(TY_DEBUGSYMLIN, &sinfo);
824     /* end of debugging stuff */
825 
826     if (s->type == SHT_NOBITS && type != OUT_RESERVE) {
827         nasm_error(ERR_WARNING, "attempt to initialize memory in"
828               " BSS section `%s': ignored", s->name);
829         s->len += realsize(type, size);
830         return;
831     }
832 
833     switch (type) {
834     case OUT_RESERVE:
835         if (s->type == SHT_PROGBITS) {
836             nasm_error(ERR_WARNING, "uninitialized space declared in"
837                   " non-BSS section `%s': zeroing", s->name);
838             elf_sect_write(s, NULL, size);
839         } else
840             s->len += size;
841         break;
842 
843     case OUT_RAWDATA:
844         elf_sect_write(s, data, size);
845         break;
846 
847     case OUT_ADDRESS:
848     {
849         bool gnu16 = false;
850         int asize = abs((int)size);
851 
852         addr = *(int64_t *)data;
853         if (segment != NO_SEG) {
854             if (segment % 2) {
855                 nasm_error(ERR_NONFATAL, "ELF format does not support"
856                       " segment base references");
857             } else {
858                 if (wrt == NO_SEG) {
859                     /*
860                      * The if() is a hack to deal with compilers which
861                      * don't handle switch() statements with 64-bit
862                      * expressions.
863                      */
864                     switch (asize) {
865                     case 1:
866                         gnu16 = true;
867                         elf_add_reloc(s, segment, 0, R_386_8);
868                         break;
869                     case 2:
870                         gnu16 = true;
871                         elf_add_reloc(s, segment, 0, R_386_16);
872                         break;
873                     case 4:
874                         elf_add_reloc(s, segment, 0, R_386_32);
875                         break;
876                     default: /* Error issued further down */
877                         break;
878                     }
879                 } else if (wrt == elf_gotpc_sect + 1) {
880                     /*
881                      * The user will supply GOT relative to $$. ELF
882                      * will let us have GOT relative to $. So we
883                      * need to fix up the data item by $-$$.
884                      */
885                     addr += s->len;
886                     elf_add_reloc(s, segment, 0, R_386_GOTPC);
887                 } else if (wrt == elf_gotoff_sect + 1) {
888                     elf_add_reloc(s, segment, 0, R_386_GOTOFF);
889                 } else if (wrt == elf_tlsie_sect + 1) {
890                     addr = elf_add_gsym_reloc(s, segment, addr, 0,
891                                               R_386_TLS_IE, true);
892                 } else if (wrt == elf_got_sect + 1) {
893                     addr = elf_add_gsym_reloc(s, segment, addr, 0,
894                                               R_386_GOT32, true);
895                 } else if (wrt == elf_sym_sect + 1) {
896                     switch (asize) {
897                     case 1:
898                         gnu16 = true;
899                         addr = elf_add_gsym_reloc(s, segment, addr, 0,
900                                                   R_386_8, false);
901                         break;
902                     case 2:
903                         gnu16 = true;
904                         addr = elf_add_gsym_reloc(s, segment, addr, 0,
905                                                   R_386_16, false);
906                         break;
907                     case 4:
908                         addr = elf_add_gsym_reloc(s, segment, addr, 0,
909                                                   R_386_32, false);
910                         break;
911                     default:
912                         break;
913                     }
914                 } else if (wrt == elf_plt_sect + 1) {
915                     nasm_error(ERR_NONFATAL, "ELF format cannot produce non-PC-"
916                           "relative PLT references");
917                 } else {
918                     nasm_error(ERR_NONFATAL, "ELF format does not support this"
919                           " use of WRT");
920                     wrt = NO_SEG; /* we can at least _try_ to continue */
921                 }
922             }
923         }
924 
925         if (gnu16) {
926             nasm_error(ERR_WARNING | ERR_WARN_GNUELF,
927                   "8- or 16-bit relocations in ELF32 is a GNU extension");
928         } else if (asize != 4 && segment != NO_SEG) {
929             nasm_error(ERR_NONFATAL, "Unsupported non-32-bit ELF relocation");
930         }
931         elf_sect_writeaddr(s, addr, asize);
932         break;
933     }
934 
935     case OUT_REL1ADR:
936         reltype = R_386_PC8;
937         bytes = 1;
938         goto rel12adr;
939     case OUT_REL2ADR:
940         reltype = R_386_PC16;
941         bytes = 2;
942         goto rel12adr;
943 
944 rel12adr:
945         addr = *(int64_t *)data - size;
946         nasm_assert(segment != segto);
947         if (segment != NO_SEG && segment % 2) {
948             nasm_error(ERR_NONFATAL, "ELF format does not support"
949                   " segment base references");
950         } else {
951             if (wrt == NO_SEG) {
952                 nasm_error(ERR_WARNING | ERR_WARN_GNUELF,
953                       "8- or 16-bit relocations in ELF is a GNU extension");
954                 elf_add_reloc(s, segment, 0, reltype);
955             } else {
956                 nasm_error(ERR_NONFATAL,
957                       "Unsupported non-32-bit ELF relocation");
958             }
959         }
960         elf_sect_writeaddr(s, addr, bytes);
961         break;
962 
963     case OUT_REL4ADR:
964         addr = *(int64_t *)data - size;
965         if (segment == segto)
966             nasm_panic("intra-segment OUT_REL4ADR");
967         if (segment != NO_SEG && segment % 2) {
968             nasm_error(ERR_NONFATAL, "ELF format does not support"
969                   " segment base references");
970         } else {
971             if (wrt == NO_SEG) {
972                 elf_add_reloc(s, segment, 0, R_386_PC32);
973             } else if (wrt == elf_plt_sect + 1) {
974                 elf_add_reloc(s, segment, 0, R_386_PLT32);
975             } else if (wrt == elf_gotpc_sect + 1 ||
976                        wrt == elf_gotoff_sect + 1 ||
977                        wrt == elf_got_sect + 1) {
978                 nasm_error(ERR_NONFATAL, "ELF format cannot produce PC-"
979                       "relative GOT references");
980             } else {
981                 nasm_error(ERR_NONFATAL, "ELF format does not support this"
982                       " use of WRT");
983                 wrt = NO_SEG;   /* we can at least _try_ to continue */
984             }
985         }
986         elf_sect_writeaddr(s, addr, 4);
987         break;
988 
989     case OUT_REL8ADR:
990         nasm_error(ERR_NONFATAL, "32-bit ELF format does not support 64-bit relocations");
991         addr = 0;
992         elf_sect_writeaddr(s, addr, 8);
993         break;
994 
995     default:
996         panic();
997     }
998 }
elf64_out(int32_t segto,const void * data,enum out_type type,uint64_t size,int32_t segment,int32_t wrt)999 static void elf64_out(int32_t segto, const void *data,
1000                       enum out_type type, uint64_t size,
1001                       int32_t segment, int32_t wrt)
1002 {
1003     struct elf_section *s;
1004     int64_t addr;
1005     int reltype, bytes;
1006     int i;
1007     static struct symlininfo sinfo;
1008 
1009     s = NULL;
1010     for (i = 0; i < nsects; i++)
1011         if (segto == sects[i]->index) {
1012             s = sects[i];
1013             break;
1014         }
1015     if (!s) {
1016         int tempint;            /* ignored */
1017         if (segto != elf_section_names(".text", 2, &tempint))
1018             nasm_panic("strange segment conditions in ELF driver");
1019         else {
1020             s = sects[nsects - 1];
1021             i = nsects - 1;
1022         }
1023     }
1024 
1025     /* again some stabs debugging stuff */
1026     sinfo.offset = s->len;
1027     sinfo.section = i;
1028     sinfo.segto = segto;
1029     sinfo.name = s->name;
1030     dfmt->debug_output(TY_DEBUGSYMLIN, &sinfo);
1031     /* end of debugging stuff */
1032 
1033     if (s->type == SHT_NOBITS && type != OUT_RESERVE) {
1034         nasm_error(ERR_WARNING, "attempt to initialize memory in"
1035               " BSS section `%s': ignored", s->name);
1036         s->len += realsize(type, size);
1037         return;
1038     }
1039 
1040     switch (type) {
1041     case OUT_RESERVE:
1042         if (s->type == SHT_PROGBITS) {
1043             nasm_error(ERR_WARNING, "uninitialized space declared in"
1044                   " non-BSS section `%s': zeroing", s->name);
1045             elf_sect_write(s, NULL, size);
1046         } else
1047             s->len += size;
1048         break;
1049 
1050     case OUT_RAWDATA:
1051         if (segment != NO_SEG)
1052             nasm_panic("OUT_RAWDATA with other than NO_SEG");
1053         elf_sect_write(s, data, size);
1054         break;
1055 
1056     case OUT_ADDRESS:
1057     {
1058         int isize = (int)size;
1059         int asize = abs((int)size);
1060 
1061         addr = *(int64_t *)data;
1062         if (segment == NO_SEG) {
1063             /* Do nothing */
1064         } else if (segment % 2) {
1065             nasm_error(ERR_NONFATAL, "ELF format does not support"
1066                   " segment base references");
1067         } else {
1068             if (wrt == NO_SEG) {
1069                 switch (isize) {
1070                 case 1:
1071                 case -1:
1072                     elf_add_reloc(s, segment, addr, R_X86_64_8);
1073                     break;
1074                 case 2:
1075                 case -2:
1076                     elf_add_reloc(s, segment, addr, R_X86_64_16);
1077                     break;
1078                 case 4:
1079                     elf_add_reloc(s, segment, addr, R_X86_64_32);
1080                     break;
1081                 case -4:
1082                     elf_add_reloc(s, segment, addr, R_X86_64_32S);
1083                     break;
1084                 case 8:
1085                 case -8:
1086                     elf_add_reloc(s, segment, addr, R_X86_64_64);
1087                     break;
1088                 default:
1089                     nasm_panic("internal error elf64-hpa-871");
1090                     break;
1091                 }
1092                 addr = 0;
1093             } else if (wrt == elf_gotpc_sect + 1) {
1094                 /*
1095                  * The user will supply GOT relative to $$. ELF
1096                  * will let us have GOT relative to $. So we
1097                  * need to fix up the data item by $-$$.
1098                  */
1099                 addr += s->len;
1100                 elf_add_reloc(s, segment, addr, R_X86_64_GOTPC32);
1101                 addr = 0;
1102             } else if (wrt == elf_gotoff_sect + 1) {
1103                 if (asize != 8) {
1104                     nasm_error(ERR_NONFATAL, "ELF64 requires ..gotoff "
1105                           "references to be qword");
1106                 } else {
1107                     elf_add_reloc(s, segment, addr, R_X86_64_GOTOFF64);
1108                     addr = 0;
1109                 }
1110             } else if (wrt == elf_got_sect + 1) {
1111                 switch (asize) {
1112                 case 4:
1113                     elf_add_gsym_reloc(s, segment, addr, 0,
1114                                        R_X86_64_GOT32, true);
1115                     addr = 0;
1116                     break;
1117                 case 8:
1118                     elf_add_gsym_reloc(s, segment, addr, 0,
1119                                        R_X86_64_GOT64, true);
1120                     addr = 0;
1121                     break;
1122                 default:
1123                     nasm_error(ERR_NONFATAL, "invalid ..got reference");
1124                     break;
1125                 }
1126             } else if (wrt == elf_sym_sect + 1) {
1127                 switch (isize) {
1128                 case 1:
1129                 case -1:
1130                     elf_add_gsym_reloc(s, segment, addr, 0,
1131                                        R_X86_64_8, false);
1132                     addr = 0;
1133                     break;
1134                 case 2:
1135                 case -2:
1136                     elf_add_gsym_reloc(s, segment, addr, 0,
1137                                        R_X86_64_16, false);
1138                     addr = 0;
1139                     break;
1140                 case 4:
1141                     elf_add_gsym_reloc(s, segment, addr, 0,
1142                                        R_X86_64_32, false);
1143                     addr = 0;
1144                     break;
1145                 case -4:
1146                     elf_add_gsym_reloc(s, segment, addr, 0,
1147                                        R_X86_64_32S, false);
1148                     addr = 0;
1149                     break;
1150                 case 8:
1151                 case -8:
1152                     elf_add_gsym_reloc(s, segment, addr, 0,
1153                                        R_X86_64_64, false);
1154                     addr = 0;
1155                     break;
1156                 default:
1157                     nasm_panic("internal error elf64-hpa-903");
1158                     break;
1159                 }
1160             } else if (wrt == elf_plt_sect + 1) {
1161                 nasm_error(ERR_NONFATAL, "ELF format cannot produce non-PC-"
1162                       "relative PLT references");
1163             } else {
1164                 nasm_error(ERR_NONFATAL, "ELF format does not support this"
1165                       " use of WRT");
1166             }
1167         }
1168         elf_sect_writeaddr(s, addr, asize);
1169         break;
1170     }
1171 
1172     case OUT_REL1ADR:
1173         reltype = R_X86_64_PC8;
1174         bytes = 1;
1175         goto rel12adr;
1176 
1177     case OUT_REL2ADR:
1178         reltype = R_X86_64_PC16;
1179         bytes = 2;
1180         goto rel12adr;
1181 
1182 rel12adr:
1183         addr = *(int64_t *)data - size;
1184         if (segment == segto)
1185             nasm_panic("intra-segment OUT_REL1ADR");
1186         if (segment == NO_SEG) {
1187             /* Do nothing */
1188         } else if (segment % 2) {
1189             nasm_error(ERR_NONFATAL, "ELF format does not support"
1190                   " segment base references");
1191         } else {
1192             if (wrt == NO_SEG) {
1193                 elf_add_reloc(s, segment, addr, reltype);
1194                 addr = 0;
1195             } else {
1196                 nasm_error(ERR_NONFATAL,
1197                       "Unsupported non-32-bit ELF relocation");
1198             }
1199         }
1200         elf_sect_writeaddr(s, addr, bytes);
1201         break;
1202 
1203     case OUT_REL4ADR:
1204         addr = *(int64_t *)data - size;
1205         if (segment == segto)
1206             nasm_panic("intra-segment OUT_REL4ADR");
1207         if (segment == NO_SEG) {
1208             /* Do nothing */
1209         } else if (segment % 2) {
1210             nasm_error(ERR_NONFATAL, "ELF64 format does not support"
1211                   " segment base references");
1212         } else {
1213             if (wrt == NO_SEG) {
1214                 elf_add_reloc(s, segment, addr, R_X86_64_PC32);
1215                 addr = 0;
1216             } else if (wrt == elf_plt_sect + 1) {
1217                 elf_add_gsym_reloc(s, segment, addr+size, size,
1218                                    R_X86_64_PLT32, true);
1219                 addr = 0;
1220             } else if (wrt == elf_gotpc_sect + 1 ||
1221                        wrt == elf_got_sect + 1) {
1222                 elf_add_gsym_reloc(s, segment, addr+size, size,
1223                                    R_X86_64_GOTPCREL, true);
1224                 addr = 0;
1225             } else if (wrt == elf_gotoff_sect + 1 ||
1226                        wrt == elf_got_sect + 1) {
1227                 nasm_error(ERR_NONFATAL, "ELF64 requires ..gotoff references to be "
1228                       "qword absolute");
1229             } else if (wrt == elf_gottpoff_sect + 1) {
1230                 elf_add_gsym_reloc(s, segment, addr+size, size,
1231                                    R_X86_64_GOTTPOFF, true);
1232                 addr = 0;
1233             } else {
1234                 nasm_error(ERR_NONFATAL, "ELF64 format does not support this"
1235                       " use of WRT");
1236             }
1237         }
1238         elf_sect_writeaddr(s, addr, 4);
1239         break;
1240 
1241     case OUT_REL8ADR:
1242         addr = *(int64_t *)data - size;
1243         if (segment == segto)
1244             nasm_panic("intra-segment OUT_REL8ADR");
1245         if (segment == NO_SEG) {
1246             /* Do nothing */
1247         } else if (segment % 2) {
1248             nasm_error(ERR_NONFATAL, "ELF64 format does not support"
1249                   " segment base references");
1250         } else {
1251             if (wrt == NO_SEG) {
1252                 elf_add_reloc(s, segment, addr, R_X86_64_PC64);
1253                 addr = 0;
1254             } else if (wrt == elf_gotpc_sect + 1 ||
1255                        wrt == elf_got_sect + 1) {
1256                 elf_add_gsym_reloc(s, segment, addr+size, size,
1257                                    R_X86_64_GOTPCREL64, true);
1258                 addr = 0;
1259             } else if (wrt == elf_gotoff_sect + 1 ||
1260                        wrt == elf_got_sect + 1) {
1261                 nasm_error(ERR_NONFATAL, "ELF64 requires ..gotoff references to be "
1262                       "absolute");
1263             } else if (wrt == elf_gottpoff_sect + 1) {
1264                 nasm_error(ERR_NONFATAL, "ELF64 requires ..gottpoff references to be "
1265                       "dword");
1266             } else {
1267                 nasm_error(ERR_NONFATAL, "ELF64 format does not support this"
1268                       " use of WRT");
1269             }
1270         }
1271         elf_sect_writeaddr(s, addr, 8);
1272         break;
1273 
1274     default:
1275         panic();
1276     }
1277 }
1278 
elfx32_out(int32_t segto,const void * data,enum out_type type,uint64_t size,int32_t segment,int32_t wrt)1279 static void elfx32_out(int32_t segto, const void *data,
1280                        enum out_type type, uint64_t size,
1281                        int32_t segment, int32_t wrt)
1282 {
1283     struct elf_section *s;
1284     int64_t addr;
1285     int reltype, bytes;
1286     int i;
1287     static struct symlininfo sinfo;
1288 
1289     s = NULL;
1290     for (i = 0; i < nsects; i++)
1291         if (segto == sects[i]->index) {
1292             s = sects[i];
1293             break;
1294         }
1295     if (!s) {
1296         int tempint;            /* ignored */
1297         if (segto != elf_section_names(".text", 2, &tempint))
1298             nasm_panic("strange segment conditions in ELF driver");
1299         else {
1300             s = sects[nsects - 1];
1301             i = nsects - 1;
1302         }
1303     }
1304 
1305     /* again some stabs debugging stuff */
1306     sinfo.offset = s->len;
1307     sinfo.section = i;
1308     sinfo.segto = segto;
1309     sinfo.name = s->name;
1310     dfmt->debug_output(TY_DEBUGSYMLIN, &sinfo);
1311     /* end of debugging stuff */
1312 
1313     if (s->type == SHT_NOBITS && type != OUT_RESERVE) {
1314         nasm_error(ERR_WARNING, "attempt to initialize memory in"
1315               " BSS section `%s': ignored", s->name);
1316         s->len += realsize(type, size);
1317         return;
1318     }
1319 
1320     switch (type) {
1321     case OUT_RESERVE:
1322         if (s->type == SHT_PROGBITS) {
1323             nasm_error(ERR_WARNING, "uninitialized space declared in"
1324                   " non-BSS section `%s': zeroing", s->name);
1325             elf_sect_write(s, NULL, size);
1326         } else
1327             s->len += size;
1328         break;
1329 
1330     case OUT_RAWDATA:
1331         if (segment != NO_SEG)
1332             nasm_panic("OUT_RAWDATA with other than NO_SEG");
1333         elf_sect_write(s, data, size);
1334         break;
1335 
1336     case OUT_ADDRESS:
1337     {
1338         int isize = (int)size;
1339         int asize = abs((int)size);
1340 
1341         addr = *(int64_t *)data;
1342         if (segment == NO_SEG) {
1343             /* Do nothing */
1344         } else if (segment % 2) {
1345             nasm_error(ERR_NONFATAL, "ELF format does not support"
1346                   " segment base references");
1347         } else {
1348             if (wrt == NO_SEG) {
1349                 switch (isize) {
1350                 case 1:
1351                 case -1:
1352                     elf_add_reloc(s, segment, addr, R_X86_64_8);
1353                     break;
1354                 case 2:
1355                 case -2:
1356                     elf_add_reloc(s, segment, addr, R_X86_64_16);
1357                     break;
1358                 case 4:
1359                     elf_add_reloc(s, segment, addr, R_X86_64_32);
1360                     break;
1361                 case -4:
1362                     elf_add_reloc(s, segment, addr, R_X86_64_32S);
1363                     break;
1364                 case 8:
1365                 case -8:
1366                     elf_add_reloc(s, segment, addr, R_X86_64_64);
1367                     break;
1368                 default:
1369                     nasm_panic("internal error elfx32-hpa-871");
1370                     break;
1371                 }
1372                 addr = 0;
1373             } else if (wrt == elf_gotpc_sect + 1) {
1374                 /*
1375                  * The user will supply GOT relative to $$. ELF
1376                  * will let us have GOT relative to $. So we
1377                  * need to fix up the data item by $-$$.
1378                  */
1379                 addr += s->len;
1380                 elf_add_reloc(s, segment, addr, R_X86_64_GOTPC32);
1381                 addr = 0;
1382             } else if (wrt == elf_gotoff_sect + 1) {
1383                 nasm_error(ERR_NONFATAL, "ELFX32 doesn't support "
1384                       "R_X86_64_GOTOFF64");
1385             } else if (wrt == elf_got_sect + 1) {
1386                 switch (asize) {
1387                 case 4:
1388                     elf_add_gsym_reloc(s, segment, addr, 0,
1389                                        R_X86_64_GOT32, true);
1390                     addr = 0;
1391                     break;
1392                 default:
1393                     nasm_error(ERR_NONFATAL, "invalid ..got reference");
1394                     break;
1395                 }
1396             } else if (wrt == elf_sym_sect + 1) {
1397                 switch (isize) {
1398                 case 1:
1399                 case -1:
1400                     elf_add_gsym_reloc(s, segment, addr, 0,
1401                                        R_X86_64_8, false);
1402                     addr = 0;
1403                     break;
1404                 case 2:
1405                 case -2:
1406                     elf_add_gsym_reloc(s, segment, addr, 0,
1407                                        R_X86_64_16, false);
1408                     addr = 0;
1409                     break;
1410                 case 4:
1411                     elf_add_gsym_reloc(s, segment, addr, 0,
1412                                        R_X86_64_32, false);
1413                     addr = 0;
1414                     break;
1415                 case -4:
1416                     elf_add_gsym_reloc(s, segment, addr, 0,
1417                                        R_X86_64_32S, false);
1418                     addr = 0;
1419                     break;
1420                 case 8:
1421                 case -8:
1422                     elf_add_gsym_reloc(s, segment, addr, 0,
1423                                        R_X86_64_64, false);
1424                     addr = 0;
1425                     break;
1426                 default:
1427                     nasm_panic("internal error elfx32-hpa-903");
1428                     break;
1429                 }
1430             } else if (wrt == elf_plt_sect + 1) {
1431                 nasm_error(ERR_NONFATAL, "ELF format cannot produce non-PC-"
1432                       "relative PLT references");
1433             } else {
1434                 nasm_error(ERR_NONFATAL, "ELF format does not support this"
1435                       " use of WRT");
1436             }
1437         }
1438         elf_sect_writeaddr(s, addr, asize);
1439         break;
1440     }
1441 
1442     case OUT_REL1ADR:
1443         reltype = R_X86_64_PC8;
1444         bytes = 1;
1445         goto rel12adr;
1446 
1447     case OUT_REL2ADR:
1448         reltype = R_X86_64_PC16;
1449         bytes = 2;
1450         goto rel12adr;
1451 
1452 rel12adr:
1453         addr = *(int64_t *)data - size;
1454         if (segment == segto)
1455             nasm_panic("intra-segment OUT_REL1ADR");
1456         if (segment == NO_SEG) {
1457             /* Do nothing */
1458         } else if (segment % 2) {
1459             nasm_error(ERR_NONFATAL, "ELF format does not support"
1460                   " segment base references");
1461         } else {
1462             if (wrt == NO_SEG) {
1463                 elf_add_reloc(s, segment, addr, reltype);
1464                 addr = 0;
1465             } else {
1466                 nasm_error(ERR_NONFATAL,
1467                       "Unsupported non-32-bit ELF relocation");
1468             }
1469         }
1470         elf_sect_writeaddr(s, addr, bytes);
1471         break;
1472 
1473     case OUT_REL4ADR:
1474         addr = *(int64_t *)data - size;
1475         if (segment == segto)
1476             nasm_panic("intra-segment OUT_REL4ADR");
1477         if (segment == NO_SEG) {
1478             /* Do nothing */
1479         } else if (segment % 2) {
1480             nasm_error(ERR_NONFATAL, "ELFX32 format does not support"
1481                   " segment base references");
1482         } else {
1483             if (wrt == NO_SEG) {
1484                 elf_add_reloc(s, segment, addr, R_X86_64_PC32);
1485                 addr = 0;
1486             } else if (wrt == elf_plt_sect + 1) {
1487                 elf_add_gsym_reloc(s, segment, addr+size, size,
1488                                    R_X86_64_PLT32, true);
1489                 addr = 0;
1490             } else if (wrt == elf_gotpc_sect + 1 ||
1491                        wrt == elf_got_sect + 1) {
1492                 elf_add_gsym_reloc(s, segment, addr+size, size,
1493                                    R_X86_64_GOTPCREL, true);
1494                 addr = 0;
1495             } else if (wrt == elf_gotoff_sect + 1 ||
1496                        wrt == elf_got_sect + 1) {
1497                 nasm_error(ERR_NONFATAL, "invalid ..gotoff reference");
1498             } else if (wrt == elf_gottpoff_sect + 1) {
1499                 elf_add_gsym_reloc(s, segment, addr+size, size,
1500                                    R_X86_64_GOTTPOFF, true);
1501                 addr = 0;
1502             } else {
1503                 nasm_error(ERR_NONFATAL, "ELFX32 format does not support this"
1504                       " use of WRT");
1505             }
1506         }
1507         elf_sect_writeaddr(s, addr, 4);
1508         break;
1509 
1510     case OUT_REL8ADR:
1511         nasm_error(ERR_NONFATAL, "32-bit ELF format does not support 64-bit relocations");
1512         addr = 0;
1513         elf_sect_writeaddr(s, addr, 8);
1514         break;
1515 
1516     default:
1517         panic();
1518     }
1519 }
1520 
elf_write(void)1521 static void elf_write(void)
1522 {
1523     int align;
1524     char *p;
1525     int i;
1526 
1527     struct SAA *symtab;
1528     int32_t symtablen, symtablocal;
1529 
1530     /*
1531      * Work out how many sections we will have. We have SHN_UNDEF,
1532      * then the flexible user sections, then the fixed sections
1533      * `.shstrtab', `.symtab' and `.strtab', then optionally
1534      * relocation sections for the user sections.
1535      */
1536     nsections = sec_numspecial + 1;
1537 	if (dfmt_is_stabs())
1538         nsections += 3;
1539     else if (dfmt_is_dwarf())
1540         nsections += 10;
1541 
1542     add_sectname("", ".shstrtab");
1543     add_sectname("", ".symtab");
1544     add_sectname("", ".strtab");
1545     for (i = 0; i < nsects; i++) {
1546         nsections++;            /* for the section itself */
1547         if (sects[i]->head) {
1548             nsections++;        /* for its relocations */
1549             add_sectname(is_elf32() ? ".rel" : ".rela", sects[i]->name);
1550         }
1551     }
1552 
1553     if (dfmt_is_stabs()) {
1554         /* in case the debug information is wanted, just add these three sections... */
1555         add_sectname("", ".stab");
1556         add_sectname("", ".stabstr");
1557         add_sectname(is_elf32() ? ".rel" : ".rela", ".stab");
1558     } else if (dfmt_is_dwarf()) {
1559         /* the dwarf debug standard specifies the following ten sections,
1560            not all of which are currently implemented,
1561            although all of them are defined. */
1562 #define debug_aranges (int64_t) (nsections-10)
1563 #define debug_info (int64_t) (nsections-7)
1564 #define debug_abbrev (int64_t) (nsections-5)
1565 #define debug_line (int64_t) (nsections-4)
1566         add_sectname("", ".debug_aranges");
1567         add_sectname(".rela", ".debug_aranges");
1568         add_sectname("", ".debug_pubnames");
1569         add_sectname("", ".debug_info");
1570         add_sectname(".rela", ".debug_info");
1571         add_sectname("", ".debug_abbrev");
1572         add_sectname("", ".debug_line");
1573         add_sectname(".rela", ".debug_line");
1574         add_sectname("", ".debug_frame");
1575         add_sectname("", ".debug_loc");
1576     }
1577 
1578     /*
1579      * Output the ELF header.
1580      */
1581     if (is_elf32() || is_elfx32()) {
1582         Elf32_Ehdr ehdr;
1583 
1584         nasm_zero(ehdr.e_ident);
1585         memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
1586         ehdr.e_ident[EI_CLASS]      = ELFCLASS32;
1587         ehdr.e_ident[EI_DATA]       = ELFDATA2LSB;
1588         ehdr.e_ident[EI_VERSION]    = EV_CURRENT;
1589         ehdr.e_ident[EI_OSABI]      = elf_osabi;
1590         ehdr.e_ident[EI_ABIVERSION] = elf_abiver;
1591 
1592         ehdr.e_type                 = cpu_to_le16(ET_REL);
1593         ehdr.e_machine              = cpu_to_le16(is_elf32() ? EM_386 : EM_X86_64);
1594         ehdr.e_version              = cpu_to_le16(EV_CURRENT);
1595         ehdr.e_entry                = 0;
1596         ehdr.e_phoff                = 0;
1597         ehdr.e_shoff                = sizeof(Elf64_Ehdr);
1598         ehdr.e_flags                = 0;
1599         ehdr.e_ehsize               = cpu_to_le16(sizeof(Elf32_Ehdr));
1600         ehdr.e_phentsize            = 0;
1601         ehdr.e_phnum                = 0;
1602         ehdr.e_shentsize            = cpu_to_le16(sizeof(Elf32_Shdr));
1603         ehdr.e_shnum                = cpu_to_le16(nsections);
1604         ehdr.e_shstrndx             = cpu_to_le16(sec_shstrtab);
1605 
1606         nasm_write(&ehdr, sizeof(ehdr), ofile);
1607         fwritezero(sizeof(Elf64_Ehdr) - sizeof(Elf32_Ehdr), ofile);
1608     } else {
1609         Elf64_Ehdr ehdr;
1610 
1611         nasm_assert(is_elf64());
1612 
1613         nasm_zero(ehdr.e_ident);
1614         memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
1615         ehdr.e_ident[EI_CLASS]      = ELFCLASS64;
1616         ehdr.e_ident[EI_DATA]       = ELFDATA2LSB;
1617         ehdr.e_ident[EI_VERSION]    = EV_CURRENT;
1618         ehdr.e_ident[EI_OSABI]      = elf_osabi;
1619         ehdr.e_ident[EI_ABIVERSION] = elf_abiver;
1620 
1621         ehdr.e_type                 = cpu_to_le16(ET_REL);
1622         ehdr.e_machine              = cpu_to_le16(EM_X86_64);
1623         ehdr.e_version              = cpu_to_le16(EV_CURRENT);
1624         ehdr.e_entry                = 0;
1625         ehdr.e_phoff                = 0;
1626         ehdr.e_shoff                = sizeof(Elf64_Ehdr);
1627         ehdr.e_flags                = 0;
1628         ehdr.e_ehsize               = cpu_to_le16(sizeof(Elf64_Ehdr));
1629         ehdr.e_phentsize            = 0;
1630         ehdr.e_phnum                = 0;
1631         ehdr.e_shentsize            = cpu_to_le16(sizeof(Elf64_Shdr));
1632         ehdr.e_shnum                = cpu_to_le16(nsections);
1633         ehdr.e_shstrndx             = cpu_to_le16(sec_shstrtab);
1634 
1635         nasm_write(&ehdr, sizeof(ehdr), ofile);
1636     }
1637 
1638     /*
1639      * Build the symbol table and relocation tables.
1640      */
1641     symtab = elf_build_symtab(&symtablen, &symtablocal);
1642     for (i = 0; i < nsects; i++)
1643         if (sects[i]->head)
1644             sects[i]->rel = elf_build_reltab(&sects[i]->rellen,
1645                                              sects[i]->head);
1646 
1647     /*
1648      * Now output the section header table.
1649      */
1650 
1651     elf_foffs = sizeof(Elf64_Ehdr) + (is_elf64() ? sizeof(Elf64_Shdr): sizeof(Elf32_Shdr)) * nsections;
1652     align = ALIGN(elf_foffs, SEC_FILEALIGN) - elf_foffs;
1653     elf_foffs += align;
1654     elf_nsect = 0;
1655     elf_sects = nasm_malloc(sizeof(*elf_sects) * nsections);
1656 
1657     /* SHN_UNDEF */
1658     elf_section_header(0, SHT_NULL, 0, NULL, false, 0, SHN_UNDEF, 0, 0, 0);
1659     p = shstrtab + 1;
1660 
1661     /* The normal sections */
1662     for (i = 0; i < nsects; i++) {
1663         elf_section_header(p - shstrtab, sects[i]->type, sects[i]->flags,
1664                            (sects[i]->type == SHT_PROGBITS ?
1665                             sects[i]->data : NULL), true,
1666                            sects[i]->len, 0, 0, sects[i]->align, 0);
1667         p += strlen(p) + 1;
1668     }
1669 
1670     /* .shstrtab */
1671     elf_section_header(p - shstrtab, SHT_STRTAB, 0, shstrtab, false,
1672                        shstrtablen, 0, 0, 1, 0);
1673     p += strlen(p) + 1;
1674 
1675     /* .symtab */
1676     if (is_elf64())
1677         elf_section_header(p - shstrtab, SHT_SYMTAB, 0, symtab, true,
1678                            symtablen, sec_strtab, symtablocal, 8, 24);
1679     else
1680         elf_section_header(p - shstrtab, SHT_SYMTAB, 0, symtab, true,
1681                            symtablen, sec_strtab, symtablocal, 4, 16);
1682     p += strlen(p) + 1;
1683 
1684     /* .strtab */
1685     elf_section_header(p - shstrtab, SHT_STRTAB, 0, strs, true,
1686                        strslen, 0, 0, 1, 0);
1687     p += strlen(p) + 1;
1688 
1689     /* The relocation sections */
1690     if (is_elf32()) {
1691         for (i = 0; i < nsects; i++) {
1692             if (sects[i]->head) {
1693                 elf_section_header(p - shstrtab, SHT_REL, 0, sects[i]->rel, true,
1694                                    sects[i]->rellen, sec_symtab, i + 1, 4, 8);
1695                 p += strlen(p) + 1;
1696             }
1697         }
1698     } else if (is_elfx32()) {
1699         for (i = 0; i < nsects; i++) {
1700             if (sects[i]->head) {
1701                 elf_section_header(p - shstrtab, SHT_RELA, 0, sects[i]->rel, true,
1702                                    sects[i]->rellen, sec_symtab, i + 1, 4, 12);
1703                 p += strlen(p) + 1;
1704             }
1705         }
1706     } else {
1707         nasm_assert(is_elf64());
1708         for (i = 0; i < nsects; i++) {
1709             if (sects[i]->head) {
1710                 elf_section_header(p - shstrtab, SHT_RELA, 0, sects[i]->rel, true,
1711                                    sects[i]->rellen, sec_symtab, i + 1, 8, 24);
1712                 p += strlen(p) + 1;
1713             }
1714         }
1715     }
1716 
1717     if (dfmt_is_stabs()) {
1718         /* for debugging information, create the last three sections
1719            which are the .stab , .stabstr and .rel.stab sections respectively */
1720 
1721         /* this function call creates the stab sections in memory */
1722         stabs_generate();
1723 
1724         if (stabbuf && stabstrbuf && stabrelbuf) {
1725             elf_section_header(p - shstrtab, SHT_PROGBITS, 0, stabbuf, false,
1726                                 stablen, sec_stabstr, 0, 4, 12);
1727             p += strlen(p) + 1;
1728 
1729             elf_section_header(p - shstrtab, SHT_STRTAB, 0, stabstrbuf, false,
1730                                stabstrlen, 0, 0, 4, 0);
1731             p += strlen(p) + 1;
1732 
1733             /* link -> symtable  info -> section to refer to */
1734             if (is_elf32()) {
1735                 elf_section_header(p - shstrtab, SHT_REL, 0, stabrelbuf, false,
1736                                    stabrellen, sec_symtab, sec_stab, 4, 8);
1737             } else {
1738                 elf_section_header(p - shstrtab, SHT_RELA, 0, stabrelbuf, false,
1739                                    stabrellen, sec_symtab, sec_stab, 4, is_elf64() ? 24 : 12);
1740             }
1741             p += strlen(p) + 1;
1742         }
1743     } else if (dfmt_is_dwarf()) {
1744             /* for dwarf debugging information, create the ten dwarf sections */
1745 
1746             /* this function call creates the dwarf sections in memory */
1747             if (dwarf_fsect)
1748                 dwarf_generate();
1749 
1750             elf_section_header(p - shstrtab, SHT_PROGBITS, 0, arangesbuf, false,
1751                                arangeslen, 0, 0, 1, 0);
1752             p += strlen(p) + 1;
1753 
1754             elf_section_header(p - shstrtab, SHT_RELA, 0, arangesrelbuf, false,
1755                                arangesrellen, sec_symtab,
1756                                is_elf64() ? debug_aranges : sec_debug_aranges,
1757                                1, is_elf64() ? 24 : 12);
1758             p += strlen(p) + 1;
1759 
1760             elf_section_header(p - shstrtab, SHT_PROGBITS, 0, pubnamesbuf,
1761                                false, pubnameslen, 0, 0, 1, 0);
1762             p += strlen(p) + 1;
1763 
1764             elf_section_header(p - shstrtab, SHT_PROGBITS, 0, infobuf, false,
1765                                infolen, 0, 0, 1, 0);
1766             p += strlen(p) + 1;
1767 
1768             elf_section_header(p - shstrtab, SHT_RELA, 0, inforelbuf, false,
1769                                inforellen, sec_symtab,
1770                                is_elf64() ? debug_info : sec_debug_info,
1771                                1, is_elf64() ? 24 : 12);
1772             p += strlen(p) + 1;
1773 
1774             elf_section_header(p - shstrtab, SHT_PROGBITS, 0, abbrevbuf, false,
1775                                abbrevlen, 0, 0, 1, 0);
1776             p += strlen(p) + 1;
1777 
1778             elf_section_header(p - shstrtab, SHT_PROGBITS, 0, linebuf, false,
1779                                linelen, 0, 0, 1, 0);
1780             p += strlen(p) + 1;
1781 
1782             elf_section_header(p - shstrtab, SHT_RELA, 0, linerelbuf, false,
1783                                linerellen, sec_symtab,
1784                                is_elf64() ? debug_line : sec_debug_line,
1785                                1, is_elf64() ? 24 : 12);
1786             p += strlen(p) + 1;
1787 
1788             elf_section_header(p - shstrtab, SHT_PROGBITS, 0, framebuf, false,
1789                                framelen, 0, 0, 8, 0);
1790             p += strlen(p) + 1;
1791 
1792             elf_section_header(p - shstrtab, SHT_PROGBITS, 0, locbuf, false,
1793                                loclen, 0, 0, 1, 0);
1794             p += strlen(p) + 1;
1795     }
1796     fwritezero(align, ofile);
1797 
1798     /*
1799      * Now output the sections.
1800      */
1801     elf_write_sections();
1802 
1803     nasm_free(elf_sects);
1804     saa_free(symtab);
1805 }
1806 
elf_build_symtab(int32_t * len,int32_t * local)1807 static struct SAA *elf_build_symtab(int32_t *len, int32_t *local)
1808 {
1809     struct SAA *s = saa_init(1L);
1810     struct elf_symbol *sym;
1811     int i;
1812 
1813     size_t usize = is_elf64() ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
1814     union {
1815         Elf32_Sym   sym32;
1816         Elf64_Sym   sym64;
1817     } u;
1818 
1819     *len = *local = 0;
1820 
1821     /*
1822      * Zero symbol first as required by spec.
1823      */
1824     saa_wbytes(s, NULL, usize);
1825     *len += usize;
1826     (*local)++;
1827 
1828     /*
1829      * Next, an entry for the file name.
1830      */
1831     if (is_elf64()) {
1832         u.sym64.st_name     = cpu_to_le32(1);
1833         u.sym64.st_info     = ELF64_ST_INFO(STB_LOCAL, STT_FILE);
1834         u.sym64.st_other    = 0;
1835         u.sym64.st_shndx    = cpu_to_le16(SHN_ABS);
1836         u.sym64.st_value    = 0;
1837         u.sym64.st_size     = 0;
1838     } else {
1839         u.sym32.st_name     = cpu_to_le32(1);
1840         u.sym32.st_value    = 0;
1841         u.sym32.st_size     = 0;
1842         u.sym32.st_info     = ELF32_ST_INFO(STB_LOCAL, STT_FILE);
1843         u.sym32.st_other    = 0;
1844         u.sym32.st_shndx    = cpu_to_le16(SHN_ABS);
1845     }
1846     saa_wbytes(s, &u, usize);
1847     *len += usize;
1848     (*local)++;
1849 
1850 
1851     /*
1852      * Now some standard symbols defining the segments, for relocation
1853      * purposes.
1854      */
1855     if (is_elf64()) {
1856         u.sym64.st_name     = 0;
1857         u.sym64.st_other    = 0;
1858         u.sym64.st_value    = 0;
1859         u.sym64.st_size     = 0;
1860         for (i = 1; i <= nsects; i++) {
1861             u.sym64.st_info      = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
1862             u.sym64.st_shndx     = cpu_to_le16(i);
1863             saa_wbytes(s, &u, usize);
1864             *len += usize;
1865             (*local)++;
1866         }
1867     } else {
1868         u.sym32.st_name     = 0;
1869         u.sym32.st_value    = 0;
1870         u.sym32.st_size     = 0;
1871         u.sym32.st_other    = 0;
1872         for (i = 1; i <= nsects; i++) {
1873             u.sym32.st_info      = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
1874             u.sym32.st_shndx     = cpu_to_le16(i);
1875             saa_wbytes(s, &u, usize);
1876             *len += usize;
1877             (*local)++;
1878         }
1879     }
1880 
1881     /*
1882      * Now the other local symbols.
1883      */
1884     saa_rewind(syms);
1885     if (is_elf64()) {
1886         while ((sym = saa_rstruct(syms))) {
1887             if (sym->type & SYM_GLOBAL)
1888                 continue;
1889             u.sym64.st_name     = cpu_to_le32(sym->strpos);
1890             u.sym64.st_info     = sym->type;
1891             u.sym64.st_other    = sym->other;
1892             u.sym64.st_shndx    = cpu_to_le16(sym->section);
1893             u.sym64.st_value    = cpu_to_le64(sym->symv.key);
1894             u.sym64.st_size     = cpu_to_le64(sym->size);
1895             saa_wbytes(s, &u, usize);
1896             *len += usize;
1897             (*local)++;
1898         }
1899         /*
1900          * dwarf needs symbols for debug sections
1901          * which are relocation targets.
1902          */
1903         if (dfmt_is_dwarf()) {
1904             dwarf_infosym = *local;
1905             u.sym64.st_name     = 0;
1906             u.sym64.st_info     = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
1907             u.sym64.st_other    = 0;
1908             u.sym64.st_shndx    = cpu_to_le16(debug_info);
1909             u.sym64.st_value    = 0;
1910             u.sym64.st_size     = 0;
1911             saa_wbytes(s, &u, usize);
1912             *len += usize;
1913             (*local)++;
1914             dwarf_abbrevsym = *local;
1915             u.sym64.st_name     = 0;
1916             u.sym64.st_info     = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
1917             u.sym64.st_other    = 0;
1918             u.sym64.st_shndx    = cpu_to_le16(debug_abbrev);
1919             u.sym64.st_value    = 0;
1920             u.sym64.st_size     = 0;
1921             saa_wbytes(s, &u, usize);
1922             *len += usize;
1923             (*local)++;
1924             dwarf_linesym = *local;
1925             u.sym64.st_name     = 0;
1926             u.sym64.st_info     = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
1927             u.sym64.st_other    = 0;
1928             u.sym64.st_shndx    = cpu_to_le16(debug_line);
1929             u.sym64.st_value    = 0;
1930             u.sym64.st_size     = 0;
1931             saa_wbytes(s, &u, usize);
1932             *len += usize;
1933             (*local)++;
1934         }
1935     } else {
1936         while ((sym = saa_rstruct(syms))) {
1937             if (sym->type & SYM_GLOBAL)
1938                 continue;
1939             u.sym32.st_name     = cpu_to_le32(sym->strpos);
1940             u.sym32.st_value    = cpu_to_le32(sym->symv.key);
1941             u.sym32.st_size     = cpu_to_le32(sym->size);
1942             u.sym32.st_info     = sym->type;
1943             u.sym32.st_other    = sym->other;
1944             u.sym32.st_shndx    = cpu_to_le16(sym->section);
1945             saa_wbytes(s, &u, usize);
1946             *len += usize;
1947             (*local)++;
1948         }
1949         /*
1950          * dwarf needs symbols for debug sections
1951          * which are relocation targets.
1952          */
1953         if (dfmt_is_dwarf()) {
1954             dwarf_infosym = *local;
1955             u.sym32.st_name     = 0;
1956             u.sym32.st_value    = 0;
1957             u.sym32.st_size     = 0;
1958             u.sym32.st_info     = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
1959             u.sym32.st_other    = 0;
1960             u.sym32.st_shndx    = cpu_to_le16(sec_debug_info);
1961             saa_wbytes(s, &u, usize);
1962             *len += usize;
1963             (*local)++;
1964             dwarf_abbrevsym = *local;
1965             u.sym32.st_name     = 0;
1966             u.sym32.st_value    = 0;
1967             u.sym32.st_size     = 0;
1968             u.sym32.st_info     = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
1969             u.sym32.st_other    = 0;
1970             u.sym32.st_shndx    = cpu_to_le16(sec_debug_abbrev);
1971             saa_wbytes(s, &u, usize);
1972             *len += usize;
1973             (*local)++;
1974             dwarf_linesym = *local;
1975             u.sym32.st_name     = 0;
1976             u.sym32.st_value    = 0;
1977             u.sym32.st_size     = 0;
1978             u.sym32.st_info     = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
1979             u.sym32.st_other    = 0;
1980             u.sym32.st_shndx    = cpu_to_le16(sec_debug_line);
1981             saa_wbytes(s, &u, usize);
1982             *len += usize;
1983             (*local)++;
1984         }
1985     }
1986 
1987     /*
1988      * Now the global symbols.
1989      */
1990     saa_rewind(syms);
1991     if (is_elf64()) {
1992         while ((sym = saa_rstruct(syms))) {
1993             if (!(sym->type & SYM_GLOBAL))
1994                 continue;
1995             u.sym64.st_name     = cpu_to_le32(sym->strpos);
1996             u.sym64.st_info     = sym->type;
1997             u.sym64.st_other    = sym->other;
1998             u.sym64.st_shndx    = cpu_to_le16(sym->section);
1999             u.sym64.st_value    = cpu_to_le64(sym->symv.key);
2000             u.sym64.st_size     = cpu_to_le64(sym->size);
2001             saa_wbytes(s, &u, usize);
2002             *len += usize;
2003         }
2004     } else {
2005         while ((sym = saa_rstruct(syms))) {
2006             if (!(sym->type & SYM_GLOBAL))
2007                 continue;
2008             u.sym32.st_name     = cpu_to_le32(sym->strpos);
2009             u.sym32.st_value    = cpu_to_le32(sym->symv.key);
2010             u.sym32.st_size     = cpu_to_le32(sym->size);
2011             u.sym32.st_info     = sym->type;
2012             u.sym32.st_other    = sym->other;
2013             u.sym32.st_shndx    = cpu_to_le16(sym->section);
2014             saa_wbytes(s, &u, usize);
2015             *len += usize;
2016         }
2017     }
2018 
2019     return s;
2020 }
2021 
elf_build_reltab(uint64_t * len,struct elf_reloc * r)2022 static struct SAA *elf_build_reltab(uint64_t *len, struct elf_reloc *r)
2023 {
2024     struct SAA *s;
2025     int32_t global_offset;
2026 
2027     size_t usize = is_elf64() ? sizeof(Elf64_Rela) :
2028         (is_elfx32() ? sizeof(Elf32_Rela) : sizeof(Elf32_Rel));
2029     union {
2030         Elf32_Rel   rel32;
2031         Elf32_Rela  rela32;
2032         Elf64_Rela  rela64;
2033     } u;
2034 
2035     if (!r)
2036         return NULL;
2037 
2038     s = saa_init(1L);
2039     *len = 0;
2040 
2041     /*
2042      * How to onvert from a global placeholder to a real symbol index;
2043      * the +2 refers to the two special entries, the null entry and
2044      * the filename entry.
2045      */
2046     global_offset = -GLOBAL_TEMP_BASE + nsects + nlocals + ndebugs + 2;
2047 
2048     if (is_elf32()) {
2049         while (r) {
2050             int32_t sym = r->symbol;
2051 
2052             if (sym >= GLOBAL_TEMP_BASE)
2053                 sym += global_offset;
2054 
2055             u.rel32.r_offset    = cpu_to_le32(r->address);
2056             u.rel32.r_info      = cpu_to_le32(ELF32_R_INFO(sym, r->type));
2057             saa_wbytes(s, &u, usize);
2058             *len += usize;
2059 
2060             r = r->next;
2061         }
2062     } else if (is_elfx32()) {
2063         while (r) {
2064             int32_t sym = r->symbol;
2065 
2066             if (sym >= GLOBAL_TEMP_BASE)
2067                 sym += global_offset;
2068 
2069             u.rela32.r_offset   = cpu_to_le32(r->address);
2070             u.rela32.r_info     = cpu_to_le32(ELF32_R_INFO(sym, r->type));
2071             u.rela32.r_addend   = cpu_to_le32(r->offset);
2072             saa_wbytes(s, &u, usize);
2073             *len += usize;
2074 
2075             r = r->next;
2076         }
2077     } else {
2078         nasm_assert(is_elf64());
2079         while (r) {
2080             int32_t sym = r->symbol;
2081 
2082             if (sym >= GLOBAL_TEMP_BASE)
2083                 sym += global_offset;
2084 
2085             u.rela64.r_offset   = cpu_to_le64(r->address);
2086             u.rela64.r_info     = cpu_to_le64(ELF64_R_INFO(sym, r->type));
2087             u.rela64.r_addend   = cpu_to_le64(r->offset);
2088             saa_wbytes(s, &u, usize);
2089             *len += usize;
2090 
2091             r = r->next;
2092         }
2093     }
2094 
2095     return s;
2096 }
2097 
elf_section_header(int name,int type,uint64_t flags,void * data,bool is_saa,uint64_t datalen,int link,int info,int align,int eltsize)2098 static void elf_section_header(int name, int type, uint64_t flags,
2099                                void *data, bool is_saa, uint64_t datalen,
2100                                int link, int info, int align, int eltsize)
2101 {
2102     union {
2103         Elf32_Shdr  shdr32;
2104         Elf64_Shdr  shdr64;
2105     } shdr;
2106 
2107     elf_sects[elf_nsect].data = data;
2108     elf_sects[elf_nsect].len = datalen;
2109     elf_sects[elf_nsect].is_saa = is_saa;
2110     elf_nsect++;
2111 
2112     if (is_elf32() || is_elfx32()) {
2113         shdr.shdr32.sh_name         = cpu_to_le32(name);
2114         shdr.shdr32.sh_type         = cpu_to_le32(type);
2115         shdr.shdr32.sh_flags        = cpu_to_le32(flags);
2116         shdr.shdr32.sh_addr         = 0;
2117         shdr.shdr32.sh_offset       = cpu_to_le32(type == SHT_NULL ? 0 : elf_foffs);
2118         shdr.shdr32.sh_size         = cpu_to_le32(datalen);
2119         if (data)
2120             elf_foffs += ALIGN(datalen, SEC_FILEALIGN);
2121         shdr.shdr32.sh_link         = cpu_to_le32(link);
2122         shdr.shdr32.sh_info         = cpu_to_le32(info);
2123         shdr.shdr32.sh_addralign    = cpu_to_le32(align);
2124         shdr.shdr32.sh_entsize      = cpu_to_le32(eltsize);
2125     } else {
2126         nasm_assert(is_elf64());
2127 
2128         shdr.shdr64.sh_name         = cpu_to_le32(name);
2129         shdr.shdr64.sh_type         = cpu_to_le32(type);
2130         shdr.shdr64.sh_flags        = cpu_to_le64(flags);
2131         shdr.shdr64.sh_addr         = 0;
2132         shdr.shdr64.sh_offset       = cpu_to_le64(type == SHT_NULL ? 0 : elf_foffs);
2133         shdr.shdr64.sh_size         = cpu_to_le32(datalen);
2134         if (data)
2135             elf_foffs += ALIGN(datalen, SEC_FILEALIGN);
2136         shdr.shdr64.sh_link        = cpu_to_le32(link);
2137         shdr.shdr64.sh_info        = cpu_to_le32(info);
2138         shdr.shdr64.sh_addralign   = cpu_to_le64(align);
2139         shdr.shdr64.sh_entsize     = cpu_to_le64(eltsize);
2140     }
2141 
2142     nasm_write(&shdr, is_elf64() ? sizeof(shdr.shdr64) : sizeof(shdr.shdr32), ofile);
2143 }
2144 
elf_write_sections(void)2145 static void elf_write_sections(void)
2146 {
2147     int i;
2148     for (i = 0; i < elf_nsect; i++)
2149         if (elf_sects[i].data) {
2150             int32_t len = elf_sects[i].len;
2151             int32_t reallen = ALIGN(len, SEC_FILEALIGN);
2152             int32_t align = reallen - len;
2153             if (elf_sects[i].is_saa)
2154                 saa_fpwrite(elf_sects[i].data, ofile);
2155             else
2156                 nasm_write(elf_sects[i].data, len, ofile);
2157             fwritezero(align, ofile);
2158         }
2159 }
2160 
elf_sect_write(struct elf_section * sect,const void * data,size_t len)2161 static void elf_sect_write(struct elf_section *sect, const void *data, size_t len)
2162 {
2163     saa_wbytes(sect->data, data, len);
2164     sect->len += len;
2165 }
2166 
elf_sect_writeaddr(struct elf_section * sect,int64_t data,size_t len)2167 static void elf_sect_writeaddr(struct elf_section *sect, int64_t data, size_t len)
2168 {
2169     saa_writeaddr(sect->data, data, len);
2170     sect->len += len;
2171 }
2172 
elf_sectalign(int32_t seg,unsigned int value)2173 static void elf_sectalign(int32_t seg, unsigned int value)
2174 {
2175     struct elf_section *s = NULL;
2176     int i;
2177 
2178     for (i = 0; i < nsects; i++) {
2179         if (sects[i]->index == seg) {
2180             s = sects[i];
2181             break;
2182         }
2183     }
2184     if (!s || !is_power2(value))
2185         return;
2186 
2187     if (value > s->align)
2188         s->align = value;
2189 }
2190 
2191 extern macros_t elf_stdmac[];
2192 
2193 /* Claim "elf" as a pragma namespace, for the future */
2194 static const struct pragma_facility elf_pragma_list[] =
2195 {
2196     { "elf", NULL },
2197     { NULL, NULL }          /* Implements the canonical output name */
2198 };
2199 
2200 
2201 static const struct dfmt elf32_df_dwarf = {
2202     "ELF32 (i386) dwarf debug format for Linux/Unix",
2203     "dwarf",
2204     dwarf_init,
2205     dwarf_linenum,
2206     null_debug_deflabel,
2207     null_debug_directive,
2208     debug_typevalue,
2209     dwarf_output,
2210     dwarf_cleanup,
2211     NULL                        /* pragma list */
2212 };
2213 
2214 static const struct dfmt elf32_df_stabs = {
2215     "ELF32 (i386) stabs debug format for Linux/Unix",
2216     "stabs",
2217     null_debug_init,
2218     stabs_linenum,
2219     null_debug_deflabel,
2220     null_debug_directive,
2221     debug_typevalue,
2222     stabs_output,
2223     stabs_cleanup,
2224     NULL                        /* pragma list */
2225 };
2226 
2227 static const struct dfmt * const elf32_debugs_arr[3] =
2228   { &elf32_df_dwarf, &elf32_df_stabs, NULL };
2229 
2230 const struct ofmt of_elf32 = {
2231     "ELF32 (i386) object files (e.g. Linux)",
2232     "elf32",
2233     ".o",
2234     0,
2235     32,
2236     elf32_debugs_arr,
2237     &elf32_df_stabs,
2238     elf_stdmac,
2239     elf_init,
2240     null_reset,
2241     nasm_do_legacy_output,
2242     elf32_out,
2243     elf_deflabel,
2244     elf_section_names,
2245     NULL,
2246     elf_sectalign,
2247     null_segbase,
2248     elf_directive,
2249     elf_cleanup,
2250     elf_pragma_list,
2251 };
2252 
2253 static const struct dfmt elf64_df_dwarf = {
2254     "ELF64 (x86-64) dwarf debug format for Linux/Unix",
2255     "dwarf",
2256     dwarf_init,
2257     dwarf_linenum,
2258     null_debug_deflabel,
2259     null_debug_directive,
2260     debug_typevalue,
2261     dwarf_output,
2262     dwarf_cleanup,
2263     NULL                        /* pragma list */
2264 };
2265 
2266 static const struct dfmt elf64_df_stabs = {
2267     "ELF64 (x86-64) stabs debug format for Linux/Unix",
2268     "stabs",
2269     null_debug_init,
2270     stabs_linenum,
2271     null_debug_deflabel,
2272     null_debug_directive,
2273     debug_typevalue,
2274     stabs_output,
2275     stabs_cleanup,
2276     NULL                        /* pragma list */
2277 };
2278 
2279 static const struct dfmt * const elf64_debugs_arr[3] =
2280   { &elf64_df_dwarf, &elf64_df_stabs, NULL };
2281 
2282 const struct ofmt of_elf64 = {
2283     "ELF64 (x86_64) object files (e.g. Linux)",
2284     "elf64",
2285     ".o",
2286     0,
2287     64,
2288     elf64_debugs_arr,
2289     &elf64_df_stabs,
2290     elf_stdmac,
2291     elf_init,
2292     null_reset,
2293     nasm_do_legacy_output,
2294     elf64_out,
2295     elf_deflabel,
2296     elf_section_names,
2297     NULL,
2298     elf_sectalign,
2299     null_segbase,
2300     elf_directive,
2301     elf_cleanup,
2302     elf_pragma_list,
2303 };
2304 
2305 static const struct dfmt elfx32_df_dwarf = {
2306     "ELFX32 (x86-64) dwarf debug format for Linux/Unix",
2307     "dwarf",
2308     dwarf_init,
2309     dwarf_linenum,
2310     null_debug_deflabel,
2311     null_debug_directive,
2312     debug_typevalue,
2313     dwarf_output,
2314     dwarf_cleanup,
2315     NULL                        /* pragma list */
2316 };
2317 
2318 static const struct dfmt elfx32_df_stabs = {
2319     "ELFX32 (x86-64) stabs debug format for Linux/Unix",
2320     "stabs",
2321     null_debug_init,
2322     stabs_linenum,
2323     null_debug_deflabel,
2324     null_debug_directive,
2325     debug_typevalue,
2326     stabs_output,
2327     stabs_cleanup,
2328     elf_pragma_list,
2329 };
2330 
2331 static const struct dfmt * const elfx32_debugs_arr[3] =
2332   { &elfx32_df_dwarf, &elfx32_df_stabs, NULL };
2333 
2334 const struct ofmt of_elfx32 = {
2335     "ELFX32 (x86_64) object files (e.g. Linux)",
2336     "elfx32",
2337     ".o",
2338     0,
2339     64,
2340     elfx32_debugs_arr,
2341     &elfx32_df_stabs,
2342     elf_stdmac,
2343     elf_init,
2344     null_reset,
2345     nasm_do_legacy_output,
2346     elfx32_out,
2347     elf_deflabel,
2348     elf_section_names,
2349     NULL,
2350     elf_sectalign,
2351     null_segbase,
2352     elf_directive,
2353     elf_cleanup,
2354     NULL                        /* pragma list */
2355 };
2356 
is_elf64(void)2357 static bool is_elf64(void)
2358 {
2359 	return ofmt == &of_elf64;
2360 }
2361 
is_elf32(void)2362 static bool is_elf32(void)
2363 {
2364 	return ofmt == &of_elf32;
2365 }
2366 
is_elfx32(void)2367 static bool is_elfx32(void)
2368 {
2369 	return ofmt == &of_elfx32;
2370 }
2371 
dfmt_is_stabs(void)2372 static bool dfmt_is_stabs(void)
2373 {
2374 	return dfmt == &elf32_df_stabs ||
2375                dfmt == &elfx32_df_stabs ||
2376                dfmt == &elf64_df_stabs;
2377 }
2378 
dfmt_is_dwarf(void)2379 static bool dfmt_is_dwarf(void)
2380 {
2381 	return dfmt == &elf32_df_dwarf ||
2382                dfmt == &elfx32_df_dwarf ||
2383                dfmt == &elf64_df_dwarf;
2384 }
2385 
2386 /* common debugging routines */
debug_typevalue(int32_t type)2387 static void debug_typevalue(int32_t type)
2388 {
2389     int32_t stype, ssize;
2390     switch (TYM_TYPE(type)) {
2391         case TY_LABEL:
2392             ssize = 0;
2393             stype = STT_NOTYPE;
2394             break;
2395         case TY_BYTE:
2396             ssize = 1;
2397             stype = STT_OBJECT;
2398             break;
2399         case TY_WORD:
2400             ssize = 2;
2401             stype = STT_OBJECT;
2402             break;
2403         case TY_DWORD:
2404             ssize = 4;
2405             stype = STT_OBJECT;
2406             break;
2407         case TY_FLOAT:
2408             ssize = 4;
2409             stype = STT_OBJECT;
2410             break;
2411         case TY_QWORD:
2412             ssize = 8;
2413             stype = STT_OBJECT;
2414             break;
2415         case TY_TBYTE:
2416             ssize = 10;
2417             stype = STT_OBJECT;
2418             break;
2419         case TY_OWORD:
2420             ssize = 16;
2421             stype = STT_OBJECT;
2422             break;
2423         case TY_YWORD:
2424             ssize = 32;
2425             stype = STT_OBJECT;
2426             break;
2427         case TY_ZWORD:
2428             ssize = 64;
2429             stype = STT_OBJECT;
2430             break;
2431         case TY_COMMON:
2432             ssize = 0;
2433             stype = STT_COMMON;
2434             break;
2435         case TY_SEG:
2436             ssize = 0;
2437             stype = STT_SECTION;
2438             break;
2439         case TY_EXTERN:
2440             ssize = 0;
2441             stype = STT_NOTYPE;
2442             break;
2443         case TY_EQU:
2444             ssize = 0;
2445             stype = STT_NOTYPE;
2446             break;
2447         default:
2448             ssize = 0;
2449             stype = STT_NOTYPE;
2450             break;
2451     }
2452     if (stype == STT_OBJECT && lastsym && !lastsym->type) {
2453         lastsym->size = ssize;
2454         lastsym->type = stype;
2455     }
2456 }
2457 
2458 /* stabs debugging routines */
2459 
stabs_linenum(const char * filename,int32_t linenumber,int32_t segto)2460 static void stabs_linenum(const char *filename, int32_t linenumber, int32_t segto)
2461 {
2462     (void)segto;
2463     if (!stabs_filename) {
2464         stabs_filename = nasm_malloc(strlen(filename) + 1);
2465         strcpy(stabs_filename, filename);
2466     } else {
2467         if (strcmp(stabs_filename, filename)) {
2468             /* yep, a memory leak...this program is one-shot anyway, so who cares...
2469                in fact, this leak comes in quite handy to maintain a list of files
2470                encountered so far in the symbol lines... */
2471 
2472             /* why not nasm_free(stabs_filename); we're done with the old one */
2473 
2474             stabs_filename = nasm_malloc(strlen(filename) + 1);
2475             strcpy(stabs_filename, filename);
2476         }
2477     }
2478     debug_immcall = 1;
2479     currentline = linenumber;
2480 }
2481 
stabs_output(int type,void * param)2482 static void stabs_output(int type, void *param)
2483 {
2484     struct symlininfo *s;
2485     struct linelist *el;
2486     if (type == TY_DEBUGSYMLIN) {
2487         if (debug_immcall) {
2488             s = (struct symlininfo *)param;
2489             if (!(sects[s->section]->flags & SHF_EXECINSTR))
2490                 return; /* line info is only collected for executable sections */
2491             numlinestabs++;
2492             el = nasm_malloc(sizeof(struct linelist));
2493             el->info.offset = s->offset;
2494             el->info.section = s->section;
2495             el->info.name = s->name;
2496             el->line = currentline;
2497             el->filename = stabs_filename;
2498             el->next = 0;
2499             if (stabslines) {
2500                 stabslines->last->next = el;
2501                 stabslines->last = el;
2502             } else {
2503                 stabslines = el;
2504                 stabslines->last = el;
2505             }
2506         }
2507     }
2508     debug_immcall = 0;
2509 }
2510 
2511 /* for creating the .stab , .stabstr and .rel.stab sections in memory */
2512 
stabs_generate(void)2513 static void stabs_generate(void)
2514 {
2515     int i, numfiles, strsize, numstabs = 0, currfile, mainfileindex;
2516     uint8_t *sbuf, *ssbuf, *rbuf, *sptr, *rptr;
2517     char **allfiles;
2518     int *fileidx;
2519 
2520     struct linelist *ptr;
2521 
2522     ptr = stabslines;
2523 
2524     allfiles = nasm_zalloc(numlinestabs * sizeof(char *));
2525     numfiles = 0;
2526     while (ptr) {
2527         if (numfiles == 0) {
2528             allfiles[0] = ptr->filename;
2529             numfiles++;
2530         } else {
2531             for (i = 0; i < numfiles; i++) {
2532                 if (!strcmp(allfiles[i], ptr->filename))
2533                     break;
2534             }
2535             if (i >= numfiles) {
2536                 allfiles[i] = ptr->filename;
2537                 numfiles++;
2538             }
2539         }
2540         ptr = ptr->next;
2541     }
2542     strsize = 1;
2543     fileidx = nasm_malloc(numfiles * sizeof(int));
2544     for (i = 0; i < numfiles; i++) {
2545         fileidx[i] = strsize;
2546         strsize += strlen(allfiles[i]) + 1;
2547     }
2548     currfile = mainfileindex = 0;
2549     for (i = 0; i < numfiles; i++) {
2550         if (!strcmp(allfiles[i], elf_module)) {
2551             currfile = mainfileindex = i;
2552             break;
2553         }
2554     }
2555 
2556     /*
2557      * worst case size of the stab buffer would be:
2558      * the sourcefiles changes each line, which would mean 1 SOL, 1 SYMLIN per line
2559      * plus one "ending" entry
2560      */
2561     sbuf = nasm_malloc((numlinestabs * 2 + 4) *
2562                                     sizeof(struct stabentry));
2563     ssbuf = nasm_malloc(strsize);
2564     rbuf = nasm_malloc(numlinestabs * (is_elf64() ? 16 : 8) * (2 + 3));
2565     rptr = rbuf;
2566 
2567     for (i = 0; i < numfiles; i++)
2568         strcpy((char *)ssbuf + fileidx[i], allfiles[i]);
2569     ssbuf[0] = 0;
2570 
2571     stabstrlen = strsize;       /* set global variable for length of stab strings */
2572 
2573     sptr = sbuf;
2574     ptr = stabslines;
2575     numstabs = 0;
2576 
2577     if (ptr) {
2578         /*
2579          * this is the first stab, its strx points to the filename of the
2580          * the source-file, the n_desc field should be set to the number
2581          * of remaining stabs
2582          */
2583         WRITE_STAB(sptr, fileidx[0], 0, 0, 0, stabstrlen);
2584 
2585         /* this is the stab for the main source file */
2586         WRITE_STAB(sptr, fileidx[mainfileindex], N_SO, 0, 0, 0);
2587 
2588         /* relocation table entry */
2589 
2590         /*
2591          * Since the symbol table has two entries before
2592          * the section symbols, the index in the info.section
2593          * member must be adjusted by adding 2
2594          */
2595 
2596         if (is_elf32()) {
2597             WRITELONG(rptr, (sptr - sbuf) - 4);
2598             WRITELONG(rptr, ((ptr->info.section + 2) << 8) | R_386_32);
2599         } else if (is_elfx32()) {
2600             WRITELONG(rptr, (sptr - sbuf) - 4);
2601             WRITELONG(rptr, ((ptr->info.section + 2) << 8) | R_X86_64_32);
2602             WRITELONG(rptr, 0);
2603         } else {
2604             nasm_assert(is_elf64());
2605             WRITEDLONG(rptr, (int64_t)(sptr - sbuf) - 4);
2606             WRITELONG(rptr, R_X86_64_32);
2607             WRITELONG(rptr, ptr->info.section + 2);
2608             WRITEDLONG(rptr, 0);
2609         }
2610         numstabs++;
2611     }
2612 
2613     if (is_elf32()) {
2614         while (ptr) {
2615             if (strcmp(allfiles[currfile], ptr->filename)) {
2616                 /* oops file has changed... */
2617                 for (i = 0; i < numfiles; i++)
2618                     if (!strcmp(allfiles[i], ptr->filename))
2619                         break;
2620                 currfile = i;
2621                 WRITE_STAB(sptr, fileidx[currfile], N_SOL, 0, 0,
2622                            ptr->info.offset);
2623                 numstabs++;
2624 
2625                 /* relocation table entry */
2626                 WRITELONG(rptr, (sptr - sbuf) - 4);
2627                 WRITELONG(rptr, ((ptr->info.section + 2) << 8) | R_386_32);
2628             }
2629 
2630             WRITE_STAB(sptr, 0, N_SLINE, 0, ptr->line, ptr->info.offset);
2631             numstabs++;
2632 
2633             /* relocation table entry */
2634             WRITELONG(rptr, (sptr - sbuf) - 4);
2635             WRITELONG(rptr, ((ptr->info.section + 2) << 8) | R_386_32);
2636 
2637             ptr = ptr->next;
2638         }
2639     } else if (is_elfx32()) {
2640         while (ptr) {
2641             if (strcmp(allfiles[currfile], ptr->filename)) {
2642                 /* oops file has changed... */
2643                 for (i = 0; i < numfiles; i++)
2644                     if (!strcmp(allfiles[i], ptr->filename))
2645                         break;
2646                 currfile = i;
2647                 WRITE_STAB(sptr, fileidx[currfile], N_SOL, 0, 0,
2648                            ptr->info.offset);
2649                 numstabs++;
2650 
2651                 /* relocation table entry */
2652                 WRITELONG(rptr, (sptr - sbuf) - 4);
2653                 WRITELONG(rptr, ((ptr->info.section + 2) << 8) | R_X86_64_32);
2654                 WRITELONG(rptr, ptr->info.offset);
2655             }
2656 
2657             WRITE_STAB(sptr, 0, N_SLINE, 0, ptr->line, ptr->info.offset);
2658             numstabs++;
2659 
2660             /* relocation table entry */
2661             WRITELONG(rptr, (sptr - sbuf) - 4);
2662             WRITELONG(rptr, ((ptr->info.section + 2) << 8) | R_X86_64_32);
2663             WRITELONG(rptr, ptr->info.offset);
2664 
2665             ptr = ptr->next;
2666         }
2667     } else {
2668         nasm_assert(is_elf64());
2669         while (ptr) {
2670             if (strcmp(allfiles[currfile], ptr->filename)) {
2671                 /* oops file has changed... */
2672                 for (i = 0; i < numfiles; i++)
2673                     if (!strcmp(allfiles[i], ptr->filename))
2674                         break;
2675                 currfile = i;
2676                 WRITE_STAB(sptr, fileidx[currfile], N_SOL, 0, 0,
2677                            ptr->info.offset);
2678                 numstabs++;
2679 
2680                 /* relocation table entry */
2681                 WRITEDLONG(rptr, (int64_t)(sptr - sbuf) - 4);
2682                 WRITELONG(rptr, R_X86_64_32);
2683                 WRITELONG(rptr, ptr->info.section + 2);
2684                 WRITEDLONG(rptr, ptr->info.offset);
2685             }
2686 
2687             WRITE_STAB(sptr, 0, N_SLINE, 0, ptr->line, ptr->info.offset);
2688             numstabs++;
2689 
2690             /* relocation table entry */
2691             WRITEDLONG(rptr, (int64_t)(sptr - sbuf) - 4);
2692             WRITELONG(rptr, R_X86_64_32);
2693             WRITELONG(rptr, ptr->info.section + 2);
2694             WRITEDLONG(rptr, ptr->info.offset);
2695 
2696             ptr = ptr->next;
2697         }
2698     }
2699 
2700     /* this is an "ending" token */
2701     WRITE_STAB(sptr, 0, N_SO, 0, 0, 0);
2702     numstabs++;
2703 
2704     ((struct stabentry *)sbuf)->n_desc = numstabs;
2705 
2706     nasm_free(allfiles);
2707     nasm_free(fileidx);
2708 
2709     stablen = (sptr - sbuf);
2710     stabrellen = (rptr - rbuf);
2711     stabrelbuf = rbuf;
2712     stabbuf = sbuf;
2713     stabstrbuf = ssbuf;
2714 }
2715 
stabs_cleanup(void)2716 static void stabs_cleanup(void)
2717 {
2718     struct linelist *ptr, *del;
2719     if (!stabslines)
2720         return;
2721 
2722     ptr = stabslines;
2723     while (ptr) {
2724         del = ptr;
2725         ptr = ptr->next;
2726         nasm_free(del);
2727     }
2728 
2729     nasm_free(stabbuf);
2730     nasm_free(stabrelbuf);
2731     nasm_free(stabstrbuf);
2732 }
2733 
2734 /* dwarf routines */
2735 
dwarf_init(void)2736 static void dwarf_init(void)
2737 {
2738     ndebugs = 3; /* 3 debug symbols */
2739 }
2740 
dwarf_linenum(const char * filename,int32_t linenumber,int32_t segto)2741 static void dwarf_linenum(const char *filename, int32_t linenumber,
2742                             int32_t segto)
2743 {
2744     (void)segto;
2745     dwarf_findfile(filename);
2746     debug_immcall = 1;
2747     currentline = linenumber;
2748 }
2749 
2750 /* called from elf_out with type == TY_DEBUGSYMLIN */
dwarf_output(int type,void * param)2751 static void dwarf_output(int type, void *param)
2752 {
2753     int ln, aa, inx, maxln, soc;
2754     struct symlininfo *s;
2755     struct SAA *plinep;
2756 
2757     (void)type;
2758 
2759     s = (struct symlininfo *)param;
2760 
2761     /* line number info is only gathered for executable sections */
2762     if (!(sects[s->section]->flags & SHF_EXECINSTR))
2763         return;
2764 
2765     /* Check if section index has changed */
2766     if (!(dwarf_csect && (dwarf_csect->section) == (s->section)))
2767         dwarf_findsect(s->section);
2768 
2769     /* do nothing unless line or file has changed */
2770     if (!debug_immcall)
2771         return;
2772 
2773     ln = currentline - dwarf_csect->line;
2774     aa = s->offset - dwarf_csect->offset;
2775     inx = dwarf_clist->line;
2776     plinep = dwarf_csect->psaa;
2777     /* check for file change */
2778     if (!(inx == dwarf_csect->file)) {
2779         saa_write8(plinep,DW_LNS_set_file);
2780         saa_write8(plinep,inx);
2781         dwarf_csect->file = inx;
2782     }
2783     /* check for line change */
2784     if (ln) {
2785         /* test if in range of special op code */
2786         maxln = line_base + line_range;
2787         soc = (ln - line_base) + (line_range * aa) + opcode_base;
2788         if (ln >= line_base && ln < maxln && soc < 256) {
2789             saa_write8(plinep,soc);
2790         } else {
2791             saa_write8(plinep,DW_LNS_advance_line);
2792             saa_wleb128s(plinep,ln);
2793             if (aa) {
2794                 saa_write8(plinep,DW_LNS_advance_pc);
2795                 saa_wleb128u(plinep,aa);
2796             }
2797             saa_write8(plinep,DW_LNS_copy);
2798         }
2799         dwarf_csect->line = currentline;
2800         dwarf_csect->offset = s->offset;
2801     }
2802 
2803     /* show change handled */
2804     debug_immcall = 0;
2805 }
2806 
2807 
dwarf_generate(void)2808 static void dwarf_generate(void)
2809 {
2810     uint8_t *pbuf;
2811     int indx;
2812     struct linelist *ftentry;
2813     struct SAA *paranges, *ppubnames, *pinfo, *pabbrev, *plines, *plinep;
2814     struct SAA *parangesrel, *plinesrel, *pinforel;
2815     struct sectlist *psect;
2816     size_t saalen, linepoff, totlen, highaddr;
2817 
2818     if (is_elf32()) {
2819         /* write epilogues for each line program range */
2820         /* and build aranges section */
2821         paranges = saa_init(1L);
2822         parangesrel = saa_init(1L);
2823         saa_write16(paranges,2);    /* dwarf version */
2824         saa_write32(parangesrel, paranges->datalen+4);
2825         saa_write32(parangesrel, (dwarf_infosym << 8) +  R_386_32); /* reloc to info */
2826         saa_write32(parangesrel, 0);
2827         saa_write32(paranges,0);    /* offset into info */
2828         saa_write8(paranges,4);     /* pointer size */
2829         saa_write8(paranges,0);     /* not segmented */
2830         saa_write32(paranges,0);    /* padding */
2831         /* iterate though sectlist entries */
2832         psect = dwarf_fsect;
2833         totlen = 0;
2834         highaddr = 0;
2835         for (indx = 0; indx < dwarf_nsections; indx++) {
2836             plinep = psect->psaa;
2837             /* Line Number Program Epilogue */
2838             saa_write8(plinep,2);           /* std op 2 */
2839             saa_write8(plinep,(sects[psect->section]->len)-psect->offset);
2840             saa_write8(plinep,DW_LNS_extended_op);
2841             saa_write8(plinep,1);           /* operand length */
2842             saa_write8(plinep,DW_LNE_end_sequence);
2843             totlen += plinep->datalen;
2844             /* range table relocation entry */
2845             saa_write32(parangesrel, paranges->datalen + 4);
2846             saa_write32(parangesrel, ((uint32_t) (psect->section + 2) << 8) +  R_386_32);
2847             saa_write32(parangesrel, (uint32_t) 0);
2848             /* range table entry */
2849             saa_write32(paranges,0x0000);   /* range start */
2850             saa_write32(paranges,sects[psect->section]->len); /* range length */
2851             highaddr += sects[psect->section]->len;
2852             /* done with this entry */
2853             psect = psect->next;
2854         }
2855         saa_write32(paranges,0);    /* null address */
2856         saa_write32(paranges,0);    /* null length */
2857         saalen = paranges->datalen;
2858         arangeslen = saalen + 4;
2859         arangesbuf = pbuf = nasm_malloc(arangeslen);
2860         WRITELONG(pbuf,saalen);     /* initial length */
2861         saa_rnbytes(paranges, pbuf, saalen);
2862         saa_free(paranges);
2863     } else if (is_elfx32()) {
2864         /* write epilogues for each line program range */
2865         /* and build aranges section */
2866         paranges = saa_init(1L);
2867         parangesrel = saa_init(1L);
2868         saa_write16(paranges,3);            /* dwarf version */
2869         saa_write32(parangesrel, paranges->datalen+4);
2870         saa_write32(parangesrel, (dwarf_infosym << 8) +  R_X86_64_32); /* reloc to info */
2871         saa_write32(parangesrel, 0);
2872         saa_write32(paranges,0);            /* offset into info */
2873         saa_write8(paranges,4);             /* pointer size */
2874         saa_write8(paranges,0);             /* not segmented */
2875         saa_write32(paranges,0);            /* padding */
2876         /* iterate though sectlist entries */
2877         psect = dwarf_fsect;
2878         totlen = 0;
2879         highaddr = 0;
2880         for (indx = 0; indx < dwarf_nsections; indx++)  {
2881             plinep = psect->psaa;
2882             /* Line Number Program Epilogue */
2883             saa_write8(plinep,2);			/* std op 2 */
2884             saa_write8(plinep,(sects[psect->section]->len)-psect->offset);
2885             saa_write8(plinep,DW_LNS_extended_op);
2886             saa_write8(plinep,1);			/* operand length */
2887             saa_write8(plinep,DW_LNE_end_sequence);
2888             totlen += plinep->datalen;
2889             /* range table relocation entry */
2890             saa_write32(parangesrel, paranges->datalen + 4);
2891             saa_write32(parangesrel, ((uint32_t) (psect->section + 2) << 8) +  R_X86_64_32);
2892             saa_write32(parangesrel, (uint32_t) 0);
2893             /* range table entry */
2894             saa_write32(paranges,0x0000);		/* range start */
2895             saa_write32(paranges,sects[psect->section]->len);	/* range length */
2896             highaddr += sects[psect->section]->len;
2897             /* done with this entry */
2898             psect = psect->next;
2899         }
2900         saa_write32(paranges,0);		/* null address */
2901         saa_write32(paranges,0);		/* null length */
2902         saalen = paranges->datalen;
2903         arangeslen = saalen + 4;
2904         arangesbuf = pbuf = nasm_malloc(arangeslen);
2905         WRITELONG(pbuf,saalen);			/* initial length */
2906         saa_rnbytes(paranges, pbuf, saalen);
2907         saa_free(paranges);
2908     } else {
2909         nasm_assert(is_elf64());
2910         /* write epilogues for each line program range */
2911         /* and build aranges section */
2912         paranges = saa_init(1L);
2913         parangesrel = saa_init(1L);
2914         saa_write16(paranges,3);            /* dwarf version */
2915         saa_write64(parangesrel, paranges->datalen+4);
2916         saa_write64(parangesrel, (dwarf_infosym << 32) +  R_X86_64_32); /* reloc to info */
2917         saa_write64(parangesrel, 0);
2918         saa_write32(paranges,0);            /* offset into info */
2919         saa_write8(paranges,8);             /* pointer size */
2920         saa_write8(paranges,0);             /* not segmented */
2921         saa_write32(paranges,0);            /* padding */
2922         /* iterate though sectlist entries */
2923         psect = dwarf_fsect;
2924         totlen = 0;
2925         highaddr = 0;
2926         for (indx = 0; indx < dwarf_nsections; indx++) {
2927             plinep = psect->psaa;
2928             /* Line Number Program Epilogue */
2929             saa_write8(plinep,2);			/* std op 2 */
2930             saa_write8(plinep,(sects[psect->section]->len)-psect->offset);
2931             saa_write8(plinep,DW_LNS_extended_op);
2932             saa_write8(plinep,1);			/* operand length */
2933             saa_write8(plinep,DW_LNE_end_sequence);
2934             totlen += plinep->datalen;
2935             /* range table relocation entry */
2936             saa_write64(parangesrel, paranges->datalen + 4);
2937             saa_write64(parangesrel, ((uint64_t) (psect->section + 2) << 32) +  R_X86_64_64);
2938             saa_write64(parangesrel, (uint64_t) 0);
2939             /* range table entry */
2940             saa_write64(paranges,0x0000);		/* range start */
2941             saa_write64(paranges,sects[psect->section]->len);	/* range length */
2942             highaddr += sects[psect->section]->len;
2943             /* done with this entry */
2944             psect = psect->next;
2945         }
2946         saa_write64(paranges,0);		/* null address */
2947         saa_write64(paranges,0);		/* null length */
2948         saalen = paranges->datalen;
2949         arangeslen = saalen + 4;
2950         arangesbuf = pbuf = nasm_malloc(arangeslen);
2951         WRITELONG(pbuf,saalen);			/* initial length */
2952         saa_rnbytes(paranges, pbuf, saalen);
2953         saa_free(paranges);
2954     }
2955 
2956     /* build rela.aranges section */
2957     arangesrellen = saalen = parangesrel->datalen;
2958     arangesrelbuf = pbuf = nasm_malloc(arangesrellen);
2959     saa_rnbytes(parangesrel, pbuf, saalen);
2960     saa_free(parangesrel);
2961 
2962     /* build pubnames section */
2963     ppubnames = saa_init(1L);
2964     saa_write16(ppubnames,3);   /* dwarf version */
2965     saa_write32(ppubnames,0);   /* offset into info */
2966     saa_write32(ppubnames,0);   /* space used in info */
2967     saa_write32(ppubnames,0);   /* end of list */
2968     saalen = ppubnames->datalen;
2969     pubnameslen = saalen + 4;
2970     pubnamesbuf = pbuf = nasm_malloc(pubnameslen);
2971     WRITELONG(pbuf,saalen);     /* initial length */
2972     saa_rnbytes(ppubnames, pbuf, saalen);
2973     saa_free(ppubnames);
2974 
2975     if (is_elf32()) {
2976         /* build info section */
2977         pinfo = saa_init(1L);
2978         pinforel = saa_init(1L);
2979         saa_write16(pinfo,2);       /* dwarf version */
2980         saa_write32(pinforel, pinfo->datalen + 4);
2981         saa_write32(pinforel, (dwarf_abbrevsym << 8) +  R_386_32); /* reloc to abbrev */
2982         saa_write32(pinforel, 0);
2983         saa_write32(pinfo,0);       /* offset into abbrev */
2984         saa_write8(pinfo,4);        /* pointer size */
2985         saa_write8(pinfo,1);        /* abbrviation number LEB128u */
2986         saa_write32(pinforel, pinfo->datalen + 4);
2987         saa_write32(pinforel, ((dwarf_fsect->section + 2) << 8) +  R_386_32);
2988         saa_write32(pinforel, 0);
2989         saa_write32(pinfo,0);       /* DW_AT_low_pc */
2990         saa_write32(pinforel, pinfo->datalen + 4);
2991         saa_write32(pinforel, ((dwarf_fsect->section + 2) << 8) +  R_386_32);
2992         saa_write32(pinforel, 0);
2993         saa_write32(pinfo,highaddr);    /* DW_AT_high_pc */
2994         saa_write32(pinforel, pinfo->datalen + 4);
2995         saa_write32(pinforel, (dwarf_linesym << 8) +  R_386_32); /* reloc to line */
2996         saa_write32(pinforel, 0);
2997         saa_write32(pinfo,0);       /* DW_AT_stmt_list */
2998         saa_wbytes(pinfo, elf_module, strlen(elf_module)+1);
2999         saa_wbytes(pinfo, nasm_signature, strlen(nasm_signature)+1);
3000         saa_write16(pinfo,DW_LANG_Mips_Assembler);
3001         saa_write8(pinfo,2);        /* abbrviation number LEB128u */
3002         saa_write32(pinforel, pinfo->datalen + 4);
3003         saa_write32(pinforel, ((dwarf_fsect->section + 2) << 8) +  R_386_32);
3004         saa_write32(pinforel, 0);
3005         saa_write32(pinfo,0);       /* DW_AT_low_pc */
3006         saa_write32(pinfo,0);       /* DW_AT_frame_base */
3007         saa_write8(pinfo,0);        /* end of entries */
3008         saalen = pinfo->datalen;
3009         infolen = saalen + 4;
3010         infobuf = pbuf = nasm_malloc(infolen);
3011         WRITELONG(pbuf,saalen);     /* initial length */
3012         saa_rnbytes(pinfo, pbuf, saalen);
3013         saa_free(pinfo);
3014     } else if (is_elfx32()) {
3015         /* build info section */
3016         pinfo = saa_init(1L);
3017         pinforel = saa_init(1L);
3018         saa_write16(pinfo,3);			/* dwarf version */
3019         saa_write32(pinforel, pinfo->datalen + 4);
3020         saa_write32(pinforel, (dwarf_abbrevsym << 8) + R_X86_64_32); /* reloc to abbrev */
3021         saa_write32(pinforel, 0);
3022         saa_write32(pinfo,0);			/* offset into abbrev */
3023         saa_write8(pinfo,4);			/* pointer size */
3024         saa_write8(pinfo,1);			/* abbrviation number LEB128u */
3025         saa_write32(pinforel, pinfo->datalen + 4);
3026         saa_write32(pinforel, ((dwarf_fsect->section + 2) << 8) + R_X86_64_32);
3027         saa_write32(pinforel, 0);
3028         saa_write32(pinfo,0);			/* DW_AT_low_pc */
3029         saa_write32(pinforel, pinfo->datalen + 4);
3030         saa_write32(pinforel, ((dwarf_fsect->section + 2) << 8) + R_X86_64_32);
3031         saa_write32(pinforel, 0);
3032         saa_write32(pinfo,highaddr);		/* DW_AT_high_pc */
3033         saa_write32(pinforel, pinfo->datalen + 4);
3034         saa_write32(pinforel, (dwarf_linesym << 8) + R_X86_64_32); /* reloc to line */
3035         saa_write32(pinforel, 0);
3036         saa_write32(pinfo,0);			/* DW_AT_stmt_list */
3037         saa_wbytes(pinfo, elf_module, strlen(elf_module)+1);
3038         saa_wbytes(pinfo, nasm_signature, strlen(nasm_signature)+1);
3039         saa_write16(pinfo,DW_LANG_Mips_Assembler);
3040         saa_write8(pinfo,2);			/* abbrviation number LEB128u */
3041         saa_write32(pinforel, pinfo->datalen + 4);
3042         saa_write32(pinforel, ((dwarf_fsect->section + 2) << 8) +  R_X86_64_32);
3043         saa_write32(pinforel, 0);
3044         saa_write32(pinfo,0);			/* DW_AT_low_pc */
3045         saa_write32(pinfo,0);			/* DW_AT_frame_base */
3046         saa_write8(pinfo,0);			/* end of entries */
3047         saalen = pinfo->datalen;
3048         infolen = saalen + 4;
3049         infobuf = pbuf = nasm_malloc(infolen);
3050         WRITELONG(pbuf,saalen);     /* initial length */
3051         saa_rnbytes(pinfo, pbuf, saalen);
3052         saa_free(pinfo);
3053     } else {
3054         nasm_assert(is_elf64());
3055         /* build info section */
3056         pinfo = saa_init(1L);
3057         pinforel = saa_init(1L);
3058         saa_write16(pinfo,3);			/* dwarf version */
3059         saa_write64(pinforel, pinfo->datalen + 4);
3060         saa_write64(pinforel, (dwarf_abbrevsym << 32) +  R_X86_64_32); /* reloc to abbrev */
3061         saa_write64(pinforel, 0);
3062         saa_write32(pinfo,0);			/* offset into abbrev */
3063         saa_write8(pinfo,8);			/* pointer size */
3064         saa_write8(pinfo,1);			/* abbrviation number LEB128u */
3065         saa_write64(pinforel, pinfo->datalen + 4);
3066         saa_write64(pinforel, ((uint64_t)(dwarf_fsect->section + 2) << 32) +  R_X86_64_64);
3067         saa_write64(pinforel, 0);
3068         saa_write64(pinfo,0);			/* DW_AT_low_pc */
3069         saa_write64(pinforel, pinfo->datalen + 4);
3070         saa_write64(pinforel, ((uint64_t)(dwarf_fsect->section + 2) << 32) +  R_X86_64_64);
3071         saa_write64(pinforel, 0);
3072         saa_write64(pinfo,highaddr);		/* DW_AT_high_pc */
3073         saa_write64(pinforel, pinfo->datalen + 4);
3074         saa_write64(pinforel, (dwarf_linesym << 32) +  R_X86_64_32); /* reloc to line */
3075         saa_write64(pinforel, 0);
3076         saa_write32(pinfo,0);			/* DW_AT_stmt_list */
3077         saa_wbytes(pinfo, elf_module, strlen(elf_module)+1);
3078         saa_wbytes(pinfo, nasm_signature, strlen(nasm_signature)+1);
3079         saa_write16(pinfo,DW_LANG_Mips_Assembler);
3080         saa_write8(pinfo,2);			/* abbrviation number LEB128u */
3081         saa_write64(pinforel, pinfo->datalen + 4);
3082         saa_write64(pinforel, ((uint64_t)(dwarf_fsect->section + 2) << 32) +  R_X86_64_64);
3083         saa_write64(pinforel, 0);
3084         saa_write64(pinfo,0);			/* DW_AT_low_pc */
3085         saa_write64(pinfo,0);			/* DW_AT_frame_base */
3086         saa_write8(pinfo,0);			/* end of entries */
3087         saalen = pinfo->datalen;
3088         infolen = saalen + 4;
3089         infobuf = pbuf = nasm_malloc(infolen);
3090         WRITELONG(pbuf,saalen);     /* initial length */
3091         saa_rnbytes(pinfo, pbuf, saalen);
3092         saa_free(pinfo);
3093     }
3094 
3095     /* build rela.info section */
3096     inforellen = saalen = pinforel->datalen;
3097     inforelbuf = pbuf = nasm_malloc(inforellen);
3098     saa_rnbytes(pinforel, pbuf, saalen);
3099     saa_free(pinforel);
3100 
3101     /* build abbrev section */
3102     pabbrev = saa_init(1L);
3103     saa_write8(pabbrev,1);      /* entry number LEB128u */
3104     saa_write8(pabbrev,DW_TAG_compile_unit);    /* tag LEB128u */
3105     saa_write8(pabbrev,1);      /* has children */
3106     /* the following attributes and forms are all LEB128u values */
3107     saa_write8(pabbrev,DW_AT_low_pc);
3108     saa_write8(pabbrev,DW_FORM_addr);
3109     saa_write8(pabbrev,DW_AT_high_pc);
3110     saa_write8(pabbrev,DW_FORM_addr);
3111     saa_write8(pabbrev,DW_AT_stmt_list);
3112     saa_write8(pabbrev,DW_FORM_data4);
3113     saa_write8(pabbrev,DW_AT_name);
3114     saa_write8(pabbrev,DW_FORM_string);
3115     saa_write8(pabbrev,DW_AT_producer);
3116     saa_write8(pabbrev,DW_FORM_string);
3117     saa_write8(pabbrev,DW_AT_language);
3118     saa_write8(pabbrev,DW_FORM_data2);
3119     saa_write16(pabbrev,0);     /* end of entry */
3120     /* LEB128u usage same as above */
3121     saa_write8(pabbrev,2);      /* entry number */
3122     saa_write8(pabbrev,DW_TAG_subprogram);
3123     saa_write8(pabbrev,0);      /* no children */
3124     saa_write8(pabbrev,DW_AT_low_pc);
3125     saa_write8(pabbrev,DW_FORM_addr);
3126     saa_write8(pabbrev,DW_AT_frame_base);
3127     saa_write8(pabbrev,DW_FORM_data4);
3128     saa_write16(pabbrev,0);     /* end of entry */
3129     /* Terminal zero entry */
3130     saa_write8(pabbrev,0);
3131     abbrevlen = saalen = pabbrev->datalen;
3132     abbrevbuf = pbuf = nasm_malloc(saalen);
3133     saa_rnbytes(pabbrev, pbuf, saalen);
3134     saa_free(pabbrev);
3135 
3136     /* build line section */
3137     /* prolog */
3138     plines = saa_init(1L);
3139     saa_write8(plines,1);           /* Minimum Instruction Length */
3140     saa_write8(plines,1);           /* Initial value of 'is_stmt' */
3141     saa_write8(plines,line_base);   /* Line Base */
3142     saa_write8(plines,line_range);  /* Line Range */
3143     saa_write8(plines,opcode_base); /* Opcode Base */
3144     /* standard opcode lengths (# of LEB128u operands) */
3145     saa_write8(plines,0);           /* Std opcode 1 length */
3146     saa_write8(plines,1);           /* Std opcode 2 length */
3147     saa_write8(plines,1);           /* Std opcode 3 length */
3148     saa_write8(plines,1);           /* Std opcode 4 length */
3149     saa_write8(plines,1);           /* Std opcode 5 length */
3150     saa_write8(plines,0);           /* Std opcode 6 length */
3151     saa_write8(plines,0);           /* Std opcode 7 length */
3152     saa_write8(plines,0);           /* Std opcode 8 length */
3153     saa_write8(plines,1);           /* Std opcode 9 length */
3154     saa_write8(plines,0);           /* Std opcode 10 length */
3155     saa_write8(plines,0);           /* Std opcode 11 length */
3156     saa_write8(plines,1);           /* Std opcode 12 length */
3157     /* Directory Table */
3158     saa_write8(plines,0);           /* End of table */
3159     /* File Name Table */
3160     ftentry = dwarf_flist;
3161     for (indx = 0; indx < dwarf_numfiles; indx++) {
3162         saa_wbytes(plines, ftentry->filename, (int32_t)(strlen(ftentry->filename) + 1));
3163         saa_write8(plines,0);       /* directory  LEB128u */
3164         saa_write8(plines,0);       /* time LEB128u */
3165         saa_write8(plines,0);       /* size LEB128u */
3166         ftentry = ftentry->next;
3167     }
3168     saa_write8(plines,0);           /* End of table */
3169     linepoff = plines->datalen;
3170     linelen = linepoff + totlen + 10;
3171     linebuf = pbuf = nasm_malloc(linelen);
3172     WRITELONG(pbuf,linelen-4);      /* initial length */
3173     WRITESHORT(pbuf,3);             /* dwarf version */
3174     WRITELONG(pbuf,linepoff);       /* offset to line number program */
3175     /* write line header */
3176     saalen = linepoff;
3177     saa_rnbytes(plines, pbuf, saalen);   /* read a given no. of bytes */
3178     pbuf += linepoff;
3179     saa_free(plines);
3180     /* concatonate line program ranges */
3181     linepoff += 13;
3182     plinesrel = saa_init(1L);
3183     psect = dwarf_fsect;
3184     if (is_elf32()) {
3185         for (indx = 0; indx < dwarf_nsections; indx++) {
3186             saa_write32(plinesrel, linepoff);
3187             saa_write32(plinesrel, ((uint32_t) (psect->section + 2) << 8) +  R_386_32);
3188             saa_write32(plinesrel, (uint32_t) 0);
3189             plinep = psect->psaa;
3190             saalen = plinep->datalen;
3191             saa_rnbytes(plinep, pbuf, saalen);
3192             pbuf += saalen;
3193             linepoff += saalen;
3194             saa_free(plinep);
3195             /* done with this entry */
3196             psect = psect->next;
3197         }
3198     } else if (is_elfx32()) {
3199         for (indx = 0; indx < dwarf_nsections; indx++) {
3200             saa_write32(plinesrel, linepoff);
3201             saa_write32(plinesrel, ((psect->section + 2) << 8) + R_X86_64_32);
3202             saa_write32(plinesrel, 0);
3203             plinep = psect->psaa;
3204             saalen = plinep->datalen;
3205             saa_rnbytes(plinep, pbuf, saalen);
3206             pbuf += saalen;
3207             linepoff += saalen;
3208             saa_free(plinep);
3209             /* done with this entry */
3210             psect = psect->next;
3211         }
3212     } else {
3213         nasm_assert(is_elf64());
3214         for (indx = 0; indx < dwarf_nsections; indx++) {
3215             saa_write64(plinesrel, linepoff);
3216             saa_write64(plinesrel, ((uint64_t) (psect->section + 2) << 32) +  R_X86_64_64);
3217             saa_write64(plinesrel, (uint64_t) 0);
3218             plinep = psect->psaa;
3219             saalen = plinep->datalen;
3220             saa_rnbytes(plinep, pbuf, saalen);
3221             pbuf += saalen;
3222             linepoff += saalen;
3223             saa_free(plinep);
3224             /* done with this entry */
3225             psect = psect->next;
3226         }
3227     }
3228 
3229     /* build rela.lines section */
3230     linerellen =saalen = plinesrel->datalen;
3231     linerelbuf = pbuf = nasm_malloc(linerellen);
3232     saa_rnbytes(plinesrel, pbuf, saalen);
3233     saa_free(plinesrel);
3234 
3235     /* build frame section */
3236     framelen = 4;
3237     framebuf = pbuf = nasm_malloc(framelen);
3238     WRITELONG(pbuf,framelen-4); /* initial length */
3239 
3240     /* build loc section */
3241     loclen = 16;
3242     locbuf = pbuf = nasm_malloc(loclen);
3243     if (is_elf32()) {
3244         WRITELONG(pbuf,0);  /* null  beginning offset */
3245         WRITELONG(pbuf,0);  /* null  ending offset */
3246     } else if (is_elfx32()) {
3247         WRITELONG(pbuf,0);  /* null  beginning offset */
3248         WRITELONG(pbuf,0);  /* null  ending offset */
3249     } else {
3250         nasm_assert(is_elf64());
3251         WRITEDLONG(pbuf,0);  /* null  beginning offset */
3252         WRITEDLONG(pbuf,0);  /* null  ending offset */
3253     }
3254 }
3255 
dwarf_cleanup(void)3256 static void dwarf_cleanup(void)
3257 {
3258     nasm_free(arangesbuf);
3259     nasm_free(arangesrelbuf);
3260     nasm_free(pubnamesbuf);
3261     nasm_free(infobuf);
3262     nasm_free(inforelbuf);
3263     nasm_free(abbrevbuf);
3264     nasm_free(linebuf);
3265     nasm_free(linerelbuf);
3266     nasm_free(framebuf);
3267     nasm_free(locbuf);
3268 }
3269 
dwarf_findfile(const char * fname)3270 static void dwarf_findfile(const char * fname)
3271 {
3272     int finx;
3273     struct linelist *match;
3274 
3275     /* return if fname is current file name */
3276     if (dwarf_clist && !(strcmp(fname, dwarf_clist->filename)))
3277         return;
3278 
3279     /* search for match */
3280     match = 0;
3281     if (dwarf_flist) {
3282         match = dwarf_flist;
3283         for (finx = 0; finx < dwarf_numfiles; finx++) {
3284             if (!(strcmp(fname, match->filename))) {
3285                 dwarf_clist = match;
3286                 return;
3287             }
3288             match = match->next;
3289         }
3290     }
3291 
3292     /* add file name to end of list */
3293     dwarf_clist = nasm_malloc(sizeof(struct linelist));
3294     dwarf_numfiles++;
3295     dwarf_clist->line = dwarf_numfiles;
3296     dwarf_clist->filename = nasm_malloc(strlen(fname) + 1);
3297     strcpy(dwarf_clist->filename,fname);
3298     dwarf_clist->next = 0;
3299     if (!dwarf_flist) {     /* if first entry */
3300         dwarf_flist = dwarf_elist = dwarf_clist;
3301         dwarf_clist->last = 0;
3302     } else {                /* chain to previous entry */
3303         dwarf_elist->next = dwarf_clist;
3304         dwarf_elist = dwarf_clist;
3305     }
3306 }
3307 
dwarf_findsect(const int index)3308 static void dwarf_findsect(const int index)
3309 {
3310     int sinx;
3311     struct sectlist *match;
3312     struct SAA *plinep;
3313 
3314     /* return if index is current section index */
3315     if (dwarf_csect && (dwarf_csect->section == index))
3316         return;
3317 
3318     /* search for match */
3319     match = 0;
3320     if (dwarf_fsect) {
3321         match = dwarf_fsect;
3322         for (sinx = 0; sinx < dwarf_nsections; sinx++) {
3323             if (match->section == index) {
3324                 dwarf_csect = match;
3325                 return;
3326             }
3327             match = match->next;
3328         }
3329     }
3330 
3331     /* add entry to end of list */
3332     dwarf_csect = nasm_malloc(sizeof(struct sectlist));
3333     dwarf_nsections++;
3334     dwarf_csect->psaa = plinep = saa_init(1L);
3335     dwarf_csect->line = 1;
3336     dwarf_csect->offset = 0;
3337     dwarf_csect->file = 1;
3338     dwarf_csect->section = index;
3339     dwarf_csect->next = 0;
3340     /* set relocatable address at start of line program */
3341     saa_write8(plinep,DW_LNS_extended_op);
3342     saa_write8(plinep,is_elf64() ? 9 : 5);   /* operand length */
3343     saa_write8(plinep,DW_LNE_set_address);
3344     if (is_elf64())
3345         saa_write64(plinep,0);  /* Start Address */
3346     else
3347         saa_write32(plinep,0);  /* Start Address */
3348 
3349     if (!dwarf_fsect) { /* if first entry */
3350         dwarf_fsect = dwarf_esect = dwarf_csect;
3351         dwarf_csect->last = 0;
3352     } else {            /* chain to previous entry */
3353         dwarf_esect->next = dwarf_csect;
3354         dwarf_esect = dwarf_csect;
3355     }
3356 }
3357 
3358 #endif /* defined(OF_ELF32) || defined(OF_ELF64) || defined(OF_ELFX32) */
3359