1/* Copyright 2016 The Fuchsia Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 */ 5 6/* 7 * This is a linker script for producing a DSO (shared library) image 8 * that is entirely read-only and trivial to map in without using a 9 * proper ELF loader. It has two segments: read-only starting at the 10 * beginning of the file, and executable code page-aligned and marked 11 * by the (hidden) symbols CODE_START and CODE_END. 12 * 13 * Ideally this could be accomplished without an explicit linker 14 * script. The linker would need an option to make the .dynamic 15 * section (aka PT_DYNAMIC segment) read-only rather than read-write; 16 * in fact that could be the default for Zircon/Fuchsia or for 17 * anything using a dynamic linker like musl's that doesn't try to 18 * write into the .dynamic section at runtime (for -shared that is; 19 * for -pie and dynamically-linked executables there is the DT_DEBUG 20 * question). The linker would need a second option to entirely 21 * segregate code from rodata (and from non-loaded parts of the file), 22 * and page-align the code segment (and pad the end to a page 23 * boundary); in fact that could be the default for any system that 24 * wants to minimize what can go into pages mapped with execute 25 * permission, which is a worthwhile trade-off of security mitigation 26 * over tiny amounts of wasted space in the ELF file. Beyond that, 27 * the linker should not generate the .got* or .plt* sections at all 28 * when there are no relocs being generated, but today's linkers still 29 * do; since some of those sections are writable, they cause the 30 * creation of a writable PT_LOAD segment by normal linker logic. 31 */ 32 33SECTIONS { 34 . = 0 + SIZEOF_HEADERS; 35 36 /* 37 * This should be defined automatically by the linker. 38 * But LLD fails to do so in the presence of a linker script. 39 * So define it explicitly. 40 * TODO(mcgrathr): If http://bugs.llvm.org/show_bug.cgi?id=32367 41 * is ever fixed, remove this. 42 */ 43 PROVIDE_HIDDEN(__ehdr_start = . - SIZEOF_HEADERS); 44 45 /* 46 * Match the non-allocated Gold version note specially, so 47 * it doesn't go into the allocated .note section below. 48 * With BFD ld, the .note clause could use: 49 * INPUT_SECTION_FLAGS(SHF_ALLOC) *(.note*) 50 * so as not to match any non-allocated note sections generically. 51 * But gold and lld do not support the INPUT_SECTION_FLAGS keyword. 52 */ 53 .note.gnu.gold-version : { *(.note.gnu.gold-version) } 54 55 .note : { 56 *(.note*) 57 } :rodata :note 58 .dynamic : { 59 *(.dynamic) 60 } :rodata :dynamic 61 .hash : { 62 *(.hash) 63 } :rodata 64 .gnu.hash : { *(.gnu.hash) } 65 .dynsym : { *(.dynsym) } 66 .dynstr : { *(.dynstr) } 67 68 .rodata : { 69 *(.rodata .rodata.* .gnu.linkonce.r.*) 70 } :rodata 71 .rodata1 : { *(.rodata1) } 72 .eh_frame_hdr : { 73 *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) 74 } :rodata :eh_frame_hdr 75 .eh_frame : { 76 KEEP(*(.eh_frame)) 77 *(.eh_frame.*) 78 } :rodata 79 .gcc_except_table : { *(.gcc_except_table*) } 80 .gnu_extab : { *(.gnu_extab*) } 81 82 /* 83 * We'd like to discard these linker-generated sections with /DISCARD/ 84 * (or convince the linker not to generate them at all). 85 * But the linker doesn't know how to do that. 86 */ 87 .got : { *(.got*) } 88 .plt : { *(.plt*) } 89 90 /* 91 * This section will only exist if there were some dynamic relocation 92 * sections generated by the linker. If this happens, the code is 93 * broken (it uses PC-sensitive static initializers or suchlike). 94 */ 95 .norelocs : { *(.rel*) } 96 ASSERT(SIZEOF(.norelocs) == 0, 97 "rodso code must avoid dynamic relocations!") 98 99 /* 100 * Likewise, this will only exist if there was some writable data. 101 */ 102 .nodata : { *(.data*) *(.sdata*) *(.bss*) *(.sbss*) } 103 ASSERT(SIZEOF(.nodata) == 0, 104 "rodso code must avoid writable data sections!") 105 106 . = ALIGN(CONSTANT(MAXPAGESIZE)); 107 108 .text : { 109 *(.text.unlikely .text.*_unlikely .text.unlikely.*) 110 *(.text.exit .text.exit.*) 111 *(.text.startup .text.startup.*) 112 *(.text.hot .text.hot.*) 113 *(.text .stub .text.* .gnu.linkonce.t.*) 114 *(.init .init.* .fini .fini.*) 115 *(.gnu.warning) 116 *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) 117 118 PROVIDE_HIDDEN(_end = .); 119 120 /* 121 * Pad out the code segment to a page boundary, so that there 122 * is only nop or zero padding visible in the memory image 123 * rather than seeing non-loaded portions of the ELF file 124 * (.shstrtab, section headers, .symtab if not stripped, etc.). 125 */ 126 . = ALIGN(CONSTANT(MAXPAGESIZE)); 127 } :code 128} 129 130PHDRS { 131 rodata PT_LOAD FLAGS(4) FILEHDR PHDRS; 132 code PT_LOAD FLAGS(5); 133 dynamic PT_DYNAMIC FLAGS(4); 134 note PT_NOTE; 135 eh_frame_hdr PT_GNU_EH_FRAME; 136} 137