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", §ionStrings); 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", §ionStrings); 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", §ionStrings); 559 unsigned long dataRelName = makeStringTableEntry(USE_RELA ? ".rela.data" : ".rel.data", §ionStrings); 560#ifndef CODEISNOTEXECUTABLE 561 unsigned long textName = makeStringTableEntry(".text", §ionStrings); 562 unsigned long textRelName = makeStringTableEntry(USE_RELA ? ".rela.text" : ".rel.text", §ionStrings); 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", §ionStrings); 567 unsigned long relDataRelName = makeStringTableEntry(USE_RELA ? ".rela.data.rel.ro" : ".rel.data.rel.ro", §ionStrings); 568 // Byte and other leaf data that do not require relocation can go in the .rodata section 569 unsigned long nRelDataName = makeStringTableEntry(".rodata", §ionStrings); 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", §ionStrings); 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", §ionStrings); 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