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