1/*
2    Title:     Write out a database as an ELF object file
3    Author:    David Matthews.
4
5    Copyright (c) 2006-7, 2011, 2016-18, 2020 David C. J. Matthews
6
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License version 2.1 as published by the Free Software Foundation.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR H PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19*/
20
21#include "config.h"
22
23#ifdef HAVE_STDLIB_H
24#include <stdlib.h>
25#endif
26
27#ifdef HAVE_STDIO_H
28#include <stdio.h>
29#endif
30
31#ifdef HAVE_STDDEF_H
32#include <stddef.h>
33#endif
34
35#ifdef HAVE_UNISTD_H
36#include <unistd.h>
37#endif
38
39#ifdef HAVE_ERRNO_H
40#include <errno.h>
41#endif
42
43#ifdef HAVE_TIME_H
44#include <time.h>
45#endif
46
47#ifdef HAVE_ASSERT_H
48#include <assert.h>
49#define ASSERT(x) assert(x)
50#else
51#define ASSERT(x)
52#endif
53
54#ifdef HAVE_ELF_H
55#include <elf.h>
56#elif defined(HAVE_ELF_ABI_H)
57#include <elf_abi.h>
58#endif
59
60#ifdef HAVE_MACHINE_RELOC_H
61#include <machine/reloc.h>
62
63#ifndef EM_X86_64
64#define EM_X86_64 EM_AMD64
65#endif
66
67#if defined(HOSTARCHITECTURE_X86_64)
68
69#ifndef R_386_PC32
70#define R_386_PC32 R_X86_64_PC32
71#endif
72
73#ifndef R_386_32
74#define R_386_32 R_X86_64_32
75#endif
76
77#ifndef R_X86_64_64
78#define R_X86_64_64 R_X86_64_64
79#endif
80
81#endif /* HOSTARCHITECTURE_X86_64 */
82
83#endif
84
85// Solaris seems to put processor-specific constants in separate files
86#ifdef HAVE_SYS_ELF_SPARC_H
87#include <sys/elf_SPARC.h>
88#endif
89#ifdef HAVE_SYS_ELF_386_H
90#include <sys/elf_386.h>
91#endif
92#ifdef HAVE_SYS_ELF_AMD64_H
93#include <sys/elf_amd64.h>
94#endif
95
96// Android has the ARM relocation symbol here
97#ifdef HAVE_ASM_ELF_H
98#include <asm/elf.h>
99#endif
100
101#ifdef HAVE_STRING_H
102#include <string.h>
103#endif
104#ifdef HAVE_SYS_UTSNAME_H
105#include <sys/utsname.h>
106#endif
107
108#include "globals.h"
109
110#include "diagnostics.h"
111#include "sys.h"
112#include "machine_dep.h"
113#include "gc.h"
114#include "mpoly.h"
115#include "scanaddrs.h"
116#include "elfexport.h"
117#include "run_time.h"
118#include "version.h"
119#include "polystring.h"
120#include "timing.h"
121
122#define sym_last_local_sym sym_data_section
123
124#if defined(HOSTARCHITECTURE_X86)
125# define HOST_E_MACHINE EM_386
126# define HOST_DIRECT_DATA_RELOC R_386_32
127# define HOST_DIRECT_FPTR_RELOC R_386_32
128# define USE_RELA 0
129#elif defined(HOSTARCHITECTURE_PPC)
130# define HOST_E_MACHINE EM_PPC
131# define HOST_DIRECT_DATA_RELOC R_PPC_ADDR32
132# define HOST_DIRECT_FPTR_RELOC R_PPC_ADDR32
133# define USE_RELA 1
134#elif defined(HOSTARCHITECTURE_PPC64)
135# define HOST_E_MACHINE EM_PPC64
136# define HOST_DIRECT_DATA_RELOC R_PPC64_ADDR64
137# define HOST_DIRECT_FPTR_RELOC R_PPC64_ADDR64
138# define USE_RELA 1
139#elif defined(HOSTARCHITECTURE_S390)
140# define HOST_E_MACHINE EM_S390
141# define HOST_DIRECT_DATA_RELOC R_390_32
142# define HOST_DIRECT_FPTR_RELOC R_390_32
143# define USE_RELA 1
144#elif defined(HOSTARCHITECTURE_S390X)
145# define HOST_E_MACHINE EM_S390
146# define HOST_DIRECT_DATA_RELOC R_390_64
147# define HOST_DIRECT_FPTR_RELOC R_390_64
148# define USE_RELA 1
149#elif defined(HOSTARCHITECTURE_SH)
150# define HOST_E_MACHINE EM_SH
151# define HOST_DIRECT_DATA_RELOC R_SH_DIR32
152# define HOST_DIRECT_FPTR_RELOC R_SH_DIR32
153# define USE_RELA 1
154#elif defined(HOSTARCHITECTURE_SPARC)
155# define HOST_E_MACHINE EM_SPARC
156# define HOST_DIRECT_DATA_RELOC R_SPARC_32
157# define HOST_DIRECT_FPTR_RELOC R_SPARC_32
158# define USE_RELA 1
159/* Sparc/Solaris, at least 2.8, requires ELF32_Rela relocations.  For some reason,
160   though, it adds the value in the location being relocated (as with ELF32_Rel
161   relocations) as well as the addend. To be safe, whenever we use an ELF32_Rela
162   relocation we always zero the location to be relocated. */
163#elif defined(HOSTARCHITECTURE_SPARC64)
164# define HOST_E_MACHINE EM_SPARCV9
165# define HOST_DIRECT_DATA_RELOC R_SPARC_64
166# define HOST_DIRECT_FPTR_RELOC R_SPARC_64
167/* Use the most relaxed memory model. At link time, the most restrictive one is
168   chosen, so it does no harm to be as permissive as possible here. */
169# define HOST_E_FLAGS EF_SPARCV9_RMO
170# define USE_RELA 1
171#elif defined(HOSTARCHITECTURE_X86_64)
172/* It seems Solaris/X86-64 only supports ELF64_Rela relocations.  It appears that
173   Linux will support either so we now use Rela on X86-64. */
174# define HOST_E_MACHINE EM_X86_64
175# define HOST_DIRECT_DATA_RELOC R_X86_64_64
176# define HOST_DIRECT_FPTR_RELOC R_X86_64_64
177# define USE_RELA 1
178#elif defined(HOSTARCHITECTURE_X32)
179# define HOST_E_MACHINE EM_X86_64
180# define HOST_DIRECT_DATA_RELOC R_X86_64_32
181# define HOST_DIRECT_FPTR_RELOC R_X86_64_32
182# define USE_RELA 1
183#elif defined(HOSTARCHITECTURE_ARM)
184# ifndef EF_ARM_EABI_VER4
185#  define EF_ARM_EABI_VER4     0x04000000
186# endif
187// When linking ARM binaries the linker checks the ABI version.  We
188// need to set the version to the same as the libraries.
189// GCC currently uses version 4.
190# define HOST_E_MACHINE EM_ARM
191# define HOST_DIRECT_DATA_RELOC R_ARM_ABS32
192# define HOST_DIRECT_FPTR_RELOC R_ARM_ABS32
193# define USE_RELA 0
194# define HOST_E_FLAGS EF_ARM_EABI_VER4
195#elif defined(HOSTARCHITECTURE_HPPA)
196# if defined(__hpux)
197#  define HOST_OSABI ELFOSABI_HPUX
198# elif defined(__NetBSD__)
199#  define HOST_OSABI ELFOSABI_NETBSD
200# elif defined(__linux__)
201#  define HOST_OSABI ELFOSABI_GNU
202# endif
203# define HOST_E_MACHINE EM_PARISC
204# define HOST_DIRECT_DATA_RELOC R_PARISC_DIR32
205# define HOST_DIRECT_FPTR_RELOC R_PARISC_PLABEL32
206# define HOST_E_FLAGS EFA_PARISC_1_0
207# define USE_RELA 1
208#elif defined(HOSTARCHITECTURE_IA64)
209# define HOST_E_MACHINE EM_IA_64
210# define HOST_DIRECT_DATA_RELOC R_IA64_DIR64LSB
211# define HOST_DIRECT_FPTR_RELOC R_IA64_FPTR64LSB
212# define HOST_E_FLAGS EF_IA_64_ABI64
213# define USE_RELA 1
214#elif defined(HOSTARCHITECTURE_AARCH64)
215# define HOST_E_MACHINE EM_AARCH64
216# define HOST_DIRECT_DATA_RELOC R_AARCH64_ABS64
217# define HOST_DIRECT_FPTR_RELOC R_AARCH64_ABS64
218# define USE_RELA 1
219#elif defined(HOSTARCHITECTURE_M68K)
220# define HOST_E_MACHINE EM_68K
221# define HOST_DIRECT_DATA_RELOC R_68K_32
222# define HOST_DIRECT_FPTR_RELOC R_68K_32
223# define USE_RELA 1
224#elif defined(HOSTARCHITECTURE_MIPS)
225# define HOST_E_MACHINE EM_MIPS
226# define HOST_DIRECT_DATA_RELOC R_MIPS_32
227# define HOST_DIRECT_FPTR_RELOC R_MIPS_32
228# ifdef __PIC__
229#  define HOST_E_FLAGS EF_MIPS_CPIC
230# endif
231# define USE_RELA 1
232#elif defined(HOSTARCHITECTURE_MIPS64)
233# define HOST_E_MACHINE EM_MIPS
234# define HOST_DIRECT_DATA_RELOC R_MIPS_64
235# define HOST_DIRECT_FPTR_RELOC R_MIPS_64
236# ifdef __PIC__
237#  define HOST_E_FLAGS (EF_MIPS_ARCH_64 | EF_MIPS_CPIC)
238# else
239#  define HOST_E_FLAGS EF_MIPS_ARCH_64
240# endif
241# define USE_RELA 1
242#elif defined(HOSTARCHITECTURE_ALPHA)
243# define HOST_E_MACHINE EM_ALPHA
244# define HOST_DIRECT_DATA_RELOC R_ALPHA_REFQUAD
245# define HOST_DIRECT_FPTR_RELOC R_ALPHA_REFQUAD
246# define USE_RELA 1
247#elif defined(HOSTARCHITECTURE_RISCV32) || defined(HOSTARCHITECTURE_RISCV64)
248# define HOST_E_MACHINE EM_RISCV
249# if defined(HOSTARCHITECTURE_RISCV32)
250#  define HOST_DIRECT_DATA_RELOC R_RISCV_32
251#  define HOST_DIRECT_FPTR_RELOC R_RISCV_32
252# else
253#  define HOST_DIRECT_DATA_RELOC R_RISCV_64
254#  define HOST_DIRECT_FPTR_RELOC R_RISCV_64
255# endif
256# if defined(__riscv_float_abi_soft)
257#  define HOST_E_FLAGS_FLOAT_ABI EF_RISCV_FLOAT_ABI_SOFT
258# elif defined(__riscv_float_abi_single)
259#  define HOST_E_FLAGS_FLOAT_ABI EF_RISCV_FLOAT_ABI_SINGLE
260# elif defined(__riscv_float_abi_double)
261#  define HOST_E_FLAGS_FLOAT_ABI EF_RISCV_FLOAT_ABI_DOUBLE
262# elif defined(__riscv_float_abi_quad)
263#  define HOST_E_FLAGS_FLOAT_ABI EF_RISCV_FLOAT_ABI_QUAD
264# else
265#  error "Unknown RISC-V float ABI"
266# endif
267# ifdef __riscv_32e
268#  define HOST_E_FLAGS_RVE __riscv_32e
269# else
270#  define HOST_E_FLAGS_RVE 0
271# endif
272# define HOST_E_FLAGS (HOST_E_FLAGS_FLOAT_ABI | HOST_E_FLAGS_RVE)
273# define USE_RELA 1
274#else
275# error "No support for exporting on this architecture"
276#endif
277
278// The first two symbols are special:
279// Zero is always special in ELF
280// 1 is used for the data section
281#define EXTRA_SYMBOLS   2
282static unsigned AreaToSym(unsigned area) { return area+EXTRA_SYMBOLS; }
283
284// Section table entries
285enum {
286    sect_initial = 0,
287    sect_sectionnametable,
288    sect_stringtable,
289    // Data and relocation entries come in here.
290    sect_data
291    // Finally the symbol table
292};
293
294// Add an external reference to the RTS
295void ELFExport::addExternalReference(void *relocAddr, const char *name, bool isFuncPtr)
296{
297    externTable.makeEntry(name);
298    // The symbol is added after the memory table entries and poly_exports
299    writeRelocation(0, relocAddr, symbolNum++, isFuncPtr);
300}
301
302// Generate the address relative to the start of the segment.
303void ELFExport::setRelocationAddress(void *p, ElfXX_Addr *reloc)
304{
305    unsigned area = findArea(p);
306    POLYUNSIGNED offset = (char*)p - (char*)memTable[area].mtOriginalAddr;
307    *reloc = offset;
308}
309
310/* Get the index corresponding to an address. */
311PolyWord ELFExport::createRelocation(PolyWord p, void *relocAddr)
312{
313    void *addr = p.AsAddress();
314    unsigned addrArea = findArea(addr);
315    POLYUNSIGNED offset = (char*)addr - (char*)memTable[addrArea].mtOriginalAddr;
316    return writeRelocation(offset, relocAddr, AreaToSym(addrArea), false);
317}
318
319PolyWord ELFExport::writeRelocation(POLYUNSIGNED offset, void *relocAddr, unsigned symbolNum, bool isFuncPtr)
320{
321#if USE_RELA
322    ElfXX_Rela reloc;
323    reloc.r_addend = offset;
324    offset = 0;
325#else
326    ElfXX_Rel reloc;
327#endif
328    // Set the offset within the section we're scanning.
329    setRelocationAddress(relocAddr, &reloc.r_offset);
330#ifdef HOSTARCHITECTURE_MIPS64
331    reloc.r_sym = symbolNum;
332    reloc.r_ssym = 0;
333    reloc.r_type = isFuncPtr ? HOST_DIRECT_FPTR_RELOC : HOST_DIRECT_DATA_RELOC;
334    reloc.r_type2 = 0;
335    reloc.r_type3 = 0;
336#else
337    reloc.r_info = ELFXX_R_INFO(symbolNum, isFuncPtr ? HOST_DIRECT_FPTR_RELOC : HOST_DIRECT_DATA_RELOC);
338#endif
339    fwrite(&reloc, sizeof(reloc), 1, exportFile);
340    relocationCount++;
341    return PolyWord::FromUnsigned(offset);
342}
343
344/* This is called for each constant within the code.
345   Print a relocation entry for the word and return a value that means
346   that the offset is saved in original word. */
347void ELFExport::ScanConstant(PolyObject *base, byte *addr, ScanRelocationKind code)
348{
349#ifndef POLYML32IN64
350    PolyObject *p = GetConstantValue(addr, code);
351
352    if (p == 0)
353        return;
354
355    void *a = p;
356    unsigned aArea = findArea(a);
357
358    // We don't need a relocation if this is relative to the current segment
359    // since the relative address will already be right.
360    if (code == PROCESS_RELOC_I386RELATIVE && aArea == findArea(addr))
361        return;
362
363    // Set the value at the address to the offset relative to the symbol.
364    POLYUNSIGNED offset = (char*)a - (char*)memTable[aArea].mtOriginalAddr;
365
366    switch (code)
367    {
368    case PROCESS_RELOC_DIRECT: // 32 or 64 bit address of target
369        {
370            PolyWord r = createRelocation(p, addr);
371            POLYUNSIGNED w = r.AsUnsigned();
372            for (unsigned i = 0; i < sizeof(PolyWord); i++)
373            {
374                addr[i] = (byte)(w & 0xff);
375                w >>= 8;
376            }
377        }
378        break;
379#if(defined(HOSTARCHITECTURE_X86) || defined(HOSTARCHITECTURE_X86_64) || \
380        defined(HOSTARCHITECTURE_X32))
381#ifdef HOSTARCHITECTURE_X86
382#define R_PC_RELATIVE R_386_PC32
383#else
384#define R_PC_RELATIVE R_X86_64_PC32
385#endif
386     case PROCESS_RELOC_I386RELATIVE:         // 32 bit relative address
387        {
388#if USE_RELA
389            ElfXX_Rela reloc;
390            reloc.r_addend = offset;
391#else
392            ElfXX_Rel reloc;
393#endif
394            setRelocationAddress(addr, &reloc.r_offset);
395            // We seem to need to subtract 4 bytes to get the correct offset in ELF
396            offset -= 4;
397            reloc.r_info = ELFXX_R_INFO(AreaToSym(aArea), R_PC_RELATIVE);
398#if USE_RELA
399            // Clear the field.  Even though it's not supposed to be used with Rela the
400            // Linux linker at least seems to add the value in here sometimes.
401            memset(addr, 0, 4);
402#else
403            for (unsigned i = 0; i < 4; i++)
404            {
405                addr[i] = (byte)(offset & 0xff);
406                offset >>= 8;
407            }
408#endif
409            fwrite(&reloc, sizeof(reloc), 1, exportFile);
410            relocationCount++;
411        }
412        break;
413#endif
414        default:
415            ASSERT(0); // Wrong type of relocation for this architecture.
416    }
417#endif
418}
419
420unsigned long ELFExport::makeStringTableEntry(const char *str, ExportStringTable *stab)
421{
422    if (str == NULL || str[0] == 0)
423        return 0; // First entry is the null string.
424    else
425        return stab->makeEntry(str);
426}
427
428void ELFExport::writeSymbol(const char *symbolName, long value, long size, int binding, int sttype, int section)
429{
430    ElfXX_Sym symbol;
431    memset(&symbol, 0, sizeof(symbol)); // Zero unused fields
432    symbol.st_name = makeStringTableEntry(symbolName, &symStrings);
433    symbol.st_value = value;
434    symbol.st_size = size;
435    symbol.st_info = ELFXX_ST_INFO(binding, sttype);
436    symbol.st_other = 0;
437    symbol.st_shndx = section;
438    fwrite(&symbol, sizeof(symbol), 1, exportFile);
439}
440
441// Set the file alignment.
442void ELFExport::alignFile(int align)
443{
444    char pad[32] = {0}; // Maximum alignment
445    int offset = ftell(exportFile);
446    if ((offset % align) == 0) return;
447    fwrite(&pad, align - (offset % align), 1, exportFile);
448}
449
450void ELFExport::createStructsRelocation(unsigned sym, size_t offset, size_t addend)
451{
452#if USE_RELA
453    ElfXX_Rela reloc;
454    reloc.r_addend = addend;
455#else
456    ElfXX_Rel reloc;
457#endif
458    reloc.r_offset = offset;
459#ifdef HOSTARCHITECTURE_MIPS64
460    reloc.r_sym = sym;
461    reloc.r_ssym = 0;
462    reloc.r_type = HOST_DIRECT_DATA_RELOC;
463    reloc.r_type2 = 0;
464    reloc.r_type3 = 0;
465#else
466    reloc.r_info = ELFXX_R_INFO(sym, HOST_DIRECT_DATA_RELOC);
467#endif
468    fwrite(&reloc, sizeof(reloc), 1, exportFile);
469    relocationCount++;
470}
471
472void ELFExport::exportStore(void)
473{
474    PolyWord    *p;
475    ElfXX_Ehdr fhdr;
476    ElfXX_Shdr *sections = 0;
477#ifdef __linux__
478    unsigned extraSections = 1; // Extra section for .note.GNU-stack
479#else
480    unsigned extraSections = 0;
481#endif
482    unsigned numSections = 0;
483    for (unsigned j = 0; j < memTableEntries; j++)
484    {
485        if ((memTable[j].mtFlags & (MTF_BYTES|MTF_WRITEABLE)) == MTF_BYTES)
486            numSections += 1;
487        else numSections += 2;
488    }
489        // The symbol table comes at the end.
490    unsigned sect_symtab = sect_data + numSections + 2;
491    numSections += 6 + extraSections;
492
493    // External symbols start after the memory table entries and "poly_exports".
494    symbolNum = EXTRA_SYMBOLS+memTableEntries+1;
495
496    // Both the string tables have an initial null entry.
497    symStrings.makeEntry("");
498    sectionStrings.makeEntry("");
499
500    // Write out initial values for the headers.  These are overwritten at the end.
501    // File header
502    memset(&fhdr, 0, sizeof(fhdr));
503    fhdr.e_ident[EI_MAG0] = 0x7f;
504    fhdr.e_ident[EI_MAG1] = 'E';
505    fhdr.e_ident[EI_MAG2] = 'L';
506    fhdr.e_ident[EI_MAG3] = 'F';
507    fhdr.e_ident[EI_CLASS] = ELFCLASSXX; // ELFCLASS32 or ELFCLASS64
508    fhdr.e_ident[EI_VERSION] = EV_CURRENT;
509#ifdef HOST_OSABI
510    fhdr.e_ident[EI_OSABI] = HOST_OSABI;
511#endif
512    {
513        union { unsigned long wrd; char chrs[sizeof(unsigned long)]; } endian;
514        endian.wrd = 1;
515        if (endian.chrs[0] == 0)
516            fhdr.e_ident[EI_DATA] = ELFDATA2MSB; // Big endian
517        else
518            fhdr.e_ident[EI_DATA] = ELFDATA2LSB; // Little endian
519    }
520    fhdr.e_type = ET_REL;
521    // The machine needs to match the machine we're compiling for
522    // even if this is actually portable code.
523    fhdr.e_machine = HOST_E_MACHINE;
524#ifdef HOST_E_FLAGS
525    fhdr.e_flags = HOST_E_FLAGS;
526#endif
527    fhdr.e_version = EV_CURRENT;
528    fhdr.e_shoff = sizeof(fhdr); // Offset to section header - immediately follows
529    fhdr.e_ehsize = sizeof(fhdr);
530    fhdr.e_shentsize = sizeof(ElfXX_Shdr);
531    fhdr.e_shnum = numSections;
532    fhdr.e_shstrndx = sect_sectionnametable; // Section name table section index;
533    fwrite(&fhdr, sizeof(fhdr), 1, exportFile); // Write it for the moment.
534
535    sections = new ElfXX_Shdr[numSections];
536    memset(sections, 0, sizeof(ElfXX_Shdr) * numSections); // Necessary?
537
538    // Set up the section header but don't write it yet.
539
540    // Section 0 - all zeros
541    sections[sect_initial].sh_type = SHT_NULL;
542    sections[sect_initial].sh_link = SHN_UNDEF;
543
544    // Section name table.
545    sections[sect_sectionnametable].sh_name = makeStringTableEntry(".shstrtab", &sectionStrings);
546    sections[sect_sectionnametable].sh_type = SHT_STRTAB;
547    sections[sect_sectionnametable].sh_addralign = sizeof(char);
548    // sections[sect_sectionnametable].sh_offset is set later
549    // sections[sect_sectionnametable].sh_size is set later
550
551    // Symbol name table.
552    sections[sect_stringtable].sh_name = makeStringTableEntry(".strtab", &sectionStrings);
553    sections[sect_stringtable].sh_type = SHT_STRTAB;
554    sections[sect_stringtable].sh_addralign = sizeof(char);
555    // sections[sect_stringtable].sh_offset is set later
556    // sections[sect_stringtable].sh_size is set later
557
558    unsigned long dataName = makeStringTableEntry(".data", &sectionStrings);
559    unsigned long dataRelName = makeStringTableEntry(USE_RELA ? ".rela.data" : ".rel.data", &sectionStrings);
560#ifndef CODEISNOTEXECUTABLE
561    unsigned long textName = makeStringTableEntry(".text", &sectionStrings);
562    unsigned long textRelName = makeStringTableEntry(USE_RELA ? ".rela.text" : ".rel.text", &sectionStrings);
563#endif
564    // The Linux linker does not like relocations in the .rodata section and marks the executable
565    // as containing text relocations.  Putting the data in a .data.rel.ro section seems to work.
566    unsigned long relDataName = makeStringTableEntry(".data.rel.ro", &sectionStrings);
567    unsigned long relDataRelName = makeStringTableEntry(USE_RELA ? ".rela.data.rel.ro" : ".rel.data.rel.ro", &sectionStrings);
568    // Byte and other leaf data that do not require relocation can go in the .rodata section
569    unsigned long nRelDataName = makeStringTableEntry(".rodata", &sectionStrings);
570
571    // Main data sections.  Each one has a relocation section.
572    unsigned s = sect_data;
573    for (unsigned i=0; i < memTableEntries; i++)
574    {
575        sections[s].sh_addralign = 8; // 8-byte alignment
576        sections[s].sh_type = SHT_PROGBITS;
577        if (memTable[i].mtFlags & MTF_WRITEABLE)
578        {
579            // Mutable areas
580            ASSERT(!(memTable[i].mtFlags & MTF_EXECUTABLE)); // Executable areas can't be writable.
581            sections[s].sh_name = dataName;
582            sections[s].sh_flags = SHF_WRITE | SHF_ALLOC;
583            s++;
584            // Mutable byte areas can contain external references so need relocation
585            sections[s].sh_name = dataRelName; // Name of relocation section
586        }
587#ifndef CODEISNOTEXECUTABLE
588        // Not if we're building the interpreted version.
589        else if (memTable[i].mtFlags & MTF_EXECUTABLE)
590        {
591            // Code areas are marked as executable.
592            sections[s].sh_name = textName;
593            sections[s].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
594            s++;
595            sections[s].sh_name = textRelName; // Name of relocation section
596        }
597#endif
598        else if (memTable[i].mtFlags & MTF_BYTES)
599        {
600            // Data that does not require relocation.
601            // Non-code immutable areas
602            sections[s].sh_name = nRelDataName;
603            sections[s].sh_flags = SHF_ALLOC;
604            s++;
605            continue; // Skip the relocation section for this
606        }
607        else
608        {
609            // Non-code immutable areas
610            sections[s].sh_name = relDataName;
611            // The .data.rel.ro has to be writable in order to be relocated.
612            // It is set to read-only after relocation.
613            sections[s].sh_flags = SHF_WRITE | SHF_ALLOC;
614            s++;
615            sections[s].sh_name = relDataRelName; // Name of relocation section
616        }
617        // sections[s].sh_size is set later
618        // sections[s].sh_offset is set later.
619        // sections[s].sh_size is set later.
620
621        // Relocation section
622        sections[s].sh_type = USE_RELA ? SHT_RELA : SHT_REL; // Contains relocation with/out explicit addends (ElfXX_Rel)
623        sections[s].sh_link = sect_symtab; // Index to symbol table
624        sections[s].sh_info = s-1; // Applies to the data section
625        sections[s].sh_addralign = sizeof(long); // Align to a word
626        sections[s].sh_entsize = USE_RELA ? sizeof(ElfXX_Rela) : sizeof(ElfXX_Rel);
627        s++;
628        // sections[s+1].sh_offset is set later.
629        // sections[s+1].sh_size is set later.
630    }
631
632    // Table data - Poly tables that describe the memory layout.
633    unsigned sect_table_data = s;
634
635    sections[sect_table_data].sh_name = dataName;
636    sections[sect_table_data].sh_type = SHT_PROGBITS;
637    sections[sect_table_data].sh_flags = SHF_WRITE | SHF_ALLOC;
638    sections[sect_table_data].sh_addralign = 8; // 8-byte alignment
639    // Table relocation
640    sections[sect_table_data+1].sh_name = dataRelName;
641    sections[sect_table_data+1].sh_type = USE_RELA ? SHT_RELA : SHT_REL; // Contains relocation with/out explicit addends (ElfXX_Rel)
642    sections[sect_table_data+1].sh_link = sect_symtab; // Index to symbol table
643    sections[sect_table_data+1].sh_info = sect_table_data; // Applies to table section
644    sections[sect_table_data+1].sh_addralign = sizeof(long); // Align to a word
645    sections[sect_table_data+1].sh_entsize = USE_RELA ? sizeof(ElfXX_Rela) : sizeof(ElfXX_Rel);
646
647    // Symbol table.
648    sections[sect_symtab].sh_name = makeStringTableEntry(".symtab", &sectionStrings);
649    sections[sect_symtab].sh_type = SHT_SYMTAB;
650    sections[sect_symtab].sh_link = sect_stringtable; // String table to use
651    sections[sect_symtab].sh_addralign = sizeof(long); // Align to a word
652    sections[sect_symtab].sh_entsize = sizeof(ElfXX_Sym);
653    // sections[sect_symtab].sh_info is set later
654    // sections[sect_symtab].sh_size is set later
655    // sections[sect_symtab].sh_offset is set later
656
657#ifdef __linux__
658    // Add a .note.GNU-stack section to indicate this does not require executable stack
659    sections[numSections-1].sh_name = makeStringTableEntry(".note.GNU-stack", &sectionStrings);
660    sections[numSections - 1].sh_type = SHT_PROGBITS;
661#endif
662
663    // Write the relocations.
664    unsigned relocSection = sect_data;
665    for (unsigned i = 0; i < memTableEntries; i++)
666    {
667        relocSection++;
668        if ((memTable[i].mtFlags & (MTF_BYTES|MTF_WRITEABLE)) == MTF_BYTES)
669            continue;
670        alignFile(sections[relocSection].sh_addralign);
671        sections[relocSection].sh_offset = ftell(exportFile);
672        relocationCount = 0;
673        // Create the relocation table and turn all addresses into offsets.
674        char *start = (char*)memTable[i].mtOriginalAddr;
675        char *end = start + memTable[i].mtLength;
676        for (p = (PolyWord*)start; p < (PolyWord*)end; )
677        {
678            p++;
679            PolyObject *obj = (PolyObject*)p;
680            POLYUNSIGNED length = obj->Length();
681            // Update any constants before processing the object
682            // We need that for relative jumps/calls in X86/64.
683            if (length != 0 && obj->IsCodeObject())
684                machineDependent->ScanConstantsWithinCode(obj, this);
685            relocateObject(obj);
686            p += length;
687        }
688        sections[relocSection].sh_size =
689            relocationCount * (USE_RELA ? sizeof(ElfXX_Rela) : sizeof(ElfXX_Rel));
690        relocSection++;
691    }
692
693    // Relocations for "exports" and "memTable";
694    alignFile(sections[sect_table_data+1].sh_addralign);
695    sections[sect_table_data+1].sh_offset = ftell(exportFile);
696    relocationCount = 0;
697    // TODO: This won't be needed if we put these in a separate section.
698    POLYUNSIGNED areaSpace = 0;
699    for (unsigned i = 0; i < memTableEntries; i++)
700        areaSpace += memTable[i].mtLength;
701
702    // Address of "memTable" within "exports". We can't use createRelocation because
703    // the position of the relocation is not in either the mutable or the immutable area.
704    size_t memTableOffset = sizeof(exportDescription); // It follows immediately after this.
705    createStructsRelocation(AreaToSym(memTableEntries), offsetof(exportDescription, memTable), memTableOffset);
706
707    // Address of "rootFunction" within "exports"
708    unsigned rootAddrArea = findArea(rootFunction);
709    size_t rootOffset = (char*)rootFunction - (char*)memTable[rootAddrArea].mtOriginalAddr;
710    createStructsRelocation(AreaToSym(rootAddrArea), offsetof(exportDescription, rootFunction), rootOffset);
711
712    // Addresses of the areas within memtable.
713    for (unsigned i = 0; i < memTableEntries; i++)
714    {
715        createStructsRelocation(AreaToSym(i),
716            sizeof(exportDescription) + i * sizeof(memoryTableEntry) + offsetof(memoryTableEntry, mtCurrentAddr),
717            0 /* No offset relative to base symbol*/);
718    }
719
720    sections[sect_table_data+1].sh_size =
721        relocationCount * (USE_RELA ? sizeof(ElfXX_Rela) : sizeof(ElfXX_Rel));
722
723    // Now the symbol table.
724    alignFile(sections[sect_symtab].sh_addralign);
725    sections[sect_symtab].sh_offset = ftell(exportFile);
726    writeSymbol("", 0, 0, 0, 0, 0); // Initial symbol
727    // Write the local symbols first.
728    writeSymbol("", 0, 0, STB_LOCAL, STT_SECTION, sect_data); // .data section
729
730    // Create symbols for the address areas.  AreaToSym assumes these come first.
731    s = sect_data;
732    for (unsigned i = 0; i < memTableEntries; i++)
733    {
734        char buff[50];
735        sprintf(buff, "area%1u", i);
736        writeSymbol(buff, 0, 0, STB_LOCAL, STT_OBJECT, s);
737        if ((memTable[i].mtFlags & (MTF_BYTES|MTF_WRITEABLE)) == MTF_BYTES)
738            s += 1;
739        else s += 2;
740    }
741
742    // Global symbols - Exported symbol for table.
743    writeSymbol("poly_exports", 0,
744        sizeof(exportDescription)+sizeof(memoryTableEntry)*memTableEntries,
745        STB_GLOBAL, STT_OBJECT, sect_table_data);
746
747    // External references
748    for (unsigned i = 0; i < externTable.stringSize; i += (unsigned)strlen(externTable.strings+i) + 1)
749        writeSymbol(externTable.strings+i, 0, 0, STB_GLOBAL, STT_FUNC, SHN_UNDEF);
750
751    sections[sect_symtab].sh_info = EXTRA_SYMBOLS+memTableEntries; // One more than last local sym
752    sections[sect_symtab].sh_size = sizeof(ElfXX_Sym) * symbolNum;
753
754    // Now the binary data.
755    unsigned dataSection = sect_data;
756    for (unsigned i = 0; i < memTableEntries; i++)
757    {
758        sections[dataSection].sh_size = memTable[i].mtLength;
759        alignFile(sections[dataSection].sh_addralign);
760        sections[dataSection].sh_offset = ftell(exportFile);
761        fwrite(memTable[i].mtOriginalAddr, 1, memTable[i].mtLength, exportFile);
762        if ((memTable[i].mtFlags & (MTF_BYTES|MTF_WRITEABLE)) == MTF_BYTES)
763            dataSection += 1;
764        else dataSection += 2;
765    }
766
767    exportDescription exports;
768    memset(&exports, 0, sizeof(exports));
769    exports.structLength = sizeof(exportDescription);
770    exports.memTableSize = sizeof(memoryTableEntry);
771    exports.memTableEntries = memTableEntries;
772    exports.memTable = USE_RELA ? 0 : (memoryTableEntry *)memTableOffset;
773    // Set the value to be the offset relative to the base of the area.  We have set a relocation
774    // already which will add the base of the area.
775    exports.rootFunction = USE_RELA ? 0 : (void*)rootOffset;
776    exports.timeStamp = getBuildTime();
777    exports.architecture = machineDependent->MachineArchitecture();
778    exports.rtsVersion = POLY_version_number;
779#ifdef POLYML32IN64
780    exports.originalBaseAddr = globalHeapBase;
781#else
782    exports.originalBaseAddr = 0;
783#endif
784
785    // Set the address values to zero before we write.  They will always
786    // be relative to their base symbol.
787    for (unsigned i = 0; i < memTableEntries; i++)
788        memTable[i].mtCurrentAddr = 0;
789
790    // Now the binary data.
791    alignFile(sections[sect_table_data].sh_addralign);
792    sections[sect_table_data].sh_offset = ftell(exportFile);
793    sections[sect_table_data].sh_size = sizeof(exportDescription) + memTableEntries*sizeof(memoryTableEntry);
794
795    fwrite(&exports, sizeof(exports), 1, exportFile);
796    fwrite(memTable, sizeof(memoryTableEntry), memTableEntries, exportFile);
797
798    // The section name table
799    sections[sect_sectionnametable].sh_offset = ftell(exportFile);
800    fwrite(sectionStrings.strings, sectionStrings.stringSize, 1, exportFile);
801    sections[sect_sectionnametable].sh_size = sectionStrings.stringSize;
802
803    // The symbol name table
804    sections[sect_stringtable].sh_offset = ftell(exportFile);
805    fwrite(symStrings.strings, symStrings.stringSize, 1, exportFile);
806    sections[sect_stringtable].sh_size = symStrings.stringSize;
807
808    // Finally the section headers.
809    alignFile(4);
810    fhdr.e_shoff = ftell(exportFile);
811    fwrite(sections, sizeof(ElfXX_Shdr) * numSections, 1, exportFile);
812
813    // Rewind to rewrite the file header with the offset of the section headers.
814    rewind(exportFile);
815    fwrite(&fhdr, sizeof(fhdr), 1, exportFile);
816    fclose(exportFile); exportFile = NULL;
817
818    delete[]sections;
819}
820