]>
Commit | Line | Data |
---|---|---|
b1195129 CC |
1 | # This shell script emits a C file. -*- C -*- |
2 | # Copyright 2023 Free Software Foundation, Inc. | |
3 | # | |
4 | # This file is part of GLD, the Gnu Linker. | |
5 | # | |
6 | # This program is free software; you can redistribute it and/or modify | |
7 | # it under the terms of the GNU General Public License as published by | |
8 | # the Free Software Foundation; either version 2 of the License, or | |
9 | # (at your option) any later version. | |
10 | # | |
11 | # This program 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 A PARTICULAR PURPOSE. See the | |
14 | # GNU General Public License for more details. | |
15 | # | |
16 | # You should have received a copy of the GNU General Public License | |
17 | # along with this program; if not, write to the Free Software | |
18 | # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. | |
19 | # | |
20 | ||
21 | # This file is sourced from elf.em, and defines extra Neutrino | |
22 | # specific routines. | |
23 | ||
24 | # NTO templates aims to refine the default ${ARCH}elf.em template. | |
25 | . "${srcdir}/emultempl/${ARCH}elf.em" | |
26 | ||
27 | cat >>e${EMULATION_NAME}.c <<EOF | |
28 | ||
29 | #include "elf/internal.h" | |
30 | #include "elf/common.h" | |
31 | #include "elf-bfd.h" | |
32 | #include "../bfd/libbfd.h" | |
33 | ||
34 | bool nto_lazy_stack = false; | |
35 | struct nto_stack_note | |
36 | { | |
37 | unsigned char stacksize[4]; | |
38 | unsigned char stackalloc[4]; | |
39 | unsigned char execstack[4]; | |
40 | }; | |
41 | ||
318d83e6 CC |
42 | static asection* |
43 | nto_create_QNX_note_section(int type) | |
44 | { | |
b1195129 CC |
45 | asection *note_sec; |
46 | flagword flags; | |
47 | Elf_External_Note *e_note; | |
318d83e6 | 48 | bfd_size_type size; |
b1195129 CC |
49 | |
50 | /* As ${ARCH}elf.em is imported and ${ARCH}_elf_create_output_section_statements | |
51 | is called before this function, stub_file should already be defined. */ | |
52 | if (!stub_file) | |
53 | { | |
54 | einfo (_("%F%P: cannot create .note section in stub BFD.\n")); | |
318d83e6 | 55 | return NULL; |
b1195129 CC |
56 | } |
57 | ||
58 | flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS | |
59 | | SEC_IN_MEMORY | SEC_LINKER_CREATED); | |
60 | note_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd, ".note", flags); | |
61 | if (! note_sec) | |
62 | { | |
63 | einfo (_("%F%P: failed to create .note section\n")); | |
318d83e6 | 64 | return NULL; |
b1195129 CC |
65 | } |
66 | ||
67 | size = offsetof (Elf_External_Note, name[sizeof "QNX"]); | |
68 | size = (size + 3) & -(bfd_size_type) 4; | |
b1195129 CC |
69 | size += sizeof (struct nto_stack_note); |
70 | note_sec->size = size; | |
71 | ||
72 | elf_section_type (note_sec) = SHT_NOTE; | |
73 | note_sec->contents = xmalloc (note_sec->size); | |
74 | e_note = (Elf_External_Note *) note_sec->contents; | |
75 | bfd_h_put_32 (stub_file->the_bfd, sizeof "QNX", &e_note->namesz); | |
76 | bfd_h_put_32 (stub_file->the_bfd, sizeof (struct nto_stack_note), &e_note->descsz); | |
318d83e6 | 77 | bfd_h_put_32 (stub_file->the_bfd, type, &e_note->type); |
b1195129 CC |
78 | memcpy (e_note->name, "QNX", sizeof "QNX"); |
79 | ||
318d83e6 CC |
80 | return note_sec; |
81 | } | |
b1195129 | 82 | |
318d83e6 CC |
83 | /* Lookup for a section holding a QNX note or create a new section. */ |
84 | static asection* | |
85 | nto_lookup_QNX_note_section(int type) | |
86 | { | |
87 | asection *stack_note_sec = NULL; | |
88 | bfd *abfd; | |
89 | for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next) | |
90 | { | |
91 | Elf_External_Note *e_note; | |
92 | asection *sec; | |
93 | ||
94 | /* QNX notes are held under a note section simply named ".note". */ | |
95 | sec = bfd_get_section_by_name (abfd, ".note"); | |
96 | if (!sec) | |
97 | continue; | |
98 | ||
99 | /* Verify that this is a QNX note of the expected type. */ | |
100 | sec->contents = bfd_malloc(sec->size); | |
101 | if (!bfd_get_section_contents (sec->owner, sec, sec->contents, (file_ptr) 0, | |
102 | sec->size)) | |
103 | einfo (_("%F%P: %pB: can't read contents of section .note: %E\n"), | |
104 | sec->owner); | |
105 | ||
106 | e_note = (Elf_External_Note *) sec->contents; | |
107 | if (! strcmp("QNX", e_note->name) && *e_note->type == type) | |
108 | { | |
109 | stack_note_sec = sec; | |
110 | /* Allow modification of this .note content. */ | |
111 | stack_note_sec->flags |= SEC_IN_MEMORY; | |
112 | break; | |
113 | } | |
114 | } | |
b1195129 | 115 | |
318d83e6 CC |
116 | if (stack_note_sec) |
117 | return stack_note_sec; | |
b1195129 | 118 | else |
318d83e6 | 119 | return nto_create_QNX_note_section(type); |
b1195129 | 120 | |
318d83e6 CC |
121 | } |
122 | ||
123 | /* Generate the QNX stack .note section. */ | |
124 | static void | |
125 | nto_add_note_section (void) { | |
126 | asection *note_sec; | |
127 | struct nto_stack_note *n_note; | |
128 | bfd_size_type h_size; | |
129 | bool is_update = false; | |
b1195129 | 130 | |
318d83e6 CC |
131 | if (nto_lazy_stack && !link_info.stacksize) |
132 | { | |
133 | einfo (_("%F%P: error: --lazy-stack must follow -zstack-size=<size>\n")); | |
134 | return; | |
135 | } | |
136 | ||
1eba15a5 CC |
137 | /* Don't create a note if none of the stack parameter have to be modified. */ |
138 | if (link_info.stacksize <= 0 && (link_info.execstack == link_info.noexecstack)) | |
139 | return; | |
140 | ||
318d83e6 CC |
141 | note_sec = nto_lookup_QNX_note_section(QNT_STACK); |
142 | if (! note_sec) | |
143 | return; | |
144 | ||
145 | /* Update QNX stack note content. */ | |
146 | h_size = note_sec->size - sizeof(struct nto_stack_note); | |
147 | n_note = (struct nto_stack_note *) (note_sec->contents + h_size); | |
148 | is_update = note_sec->owner != stub_file->the_bfd; | |
149 | ||
150 | if (link_info.stacksize > 0) | |
151 | bfd_h_put_32 (note_sec->owner, link_info.stacksize, &n_note->stacksize); | |
152 | else if (!is_update) | |
153 | bfd_h_put_32 (note_sec->owner, 0, &n_note->stacksize); | |
154 | ||
155 | if (nto_lazy_stack || (!is_update && link_info.stacksize <= 0)) | |
156 | bfd_h_put_32 (note_sec->owner, 4096, &n_note->stackalloc); | |
157 | else if (link_info.stacksize > 0) | |
158 | bfd_h_put_32 (note_sec->owner, link_info.stacksize, &n_note->stackalloc); | |
159 | ||
160 | if (link_info.execstack) | |
161 | bfd_h_put_32 (note_sec->owner, 0, &n_note->execstack); | |
162 | else if (!is_update || link_info.noexecstack) | |
163 | bfd_h_put_32 (note_sec->owner, 1, &n_note->execstack); | |
b1195129 CC |
164 | } |
165 | ||
166 | static void | |
318d83e6 | 167 | nto_after_open (void) |
b1195129 | 168 | { |
b1195129 | 169 | nto_add_note_section(); |
318d83e6 | 170 | gld${EMULATION_NAME}_after_open (); |
b1195129 CC |
171 | } |
172 | ||
173 | EOF | |
174 | ||
175 | # Define some shell vars to insert bits of code into the standard elf | |
176 | # parse_args and list_options functions. | |
177 | # | |
178 | ||
179 | PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}' | |
180 | enum nto_options | |
181 | { | |
182 | OPTION_STACK = 500, | |
183 | OPTION_LAZY_STACK, | |
184 | }; | |
185 | ' | |
186 | ||
187 | PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}' | |
188 | { "stack", required_argument, NULL, OPTION_STACK }, | |
189 | { "lazy-stack", no_argument, NULL, OPTION_LAZY_STACK }, | |
190 | ' | |
191 | ||
192 | PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}' | |
193 | fprintf (file, _("\ | |
194 | --stack <size> Set size of the initial stack\n\ | |
195 | --lazy-stack Set lazy allocation of stack\n\ | |
196 | ")); | |
197 | ' | |
198 | ||
199 | PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' | |
200 | case OPTION_STACK: | |
201 | { | |
202 | char *end; | |
203 | link_info.stacksize = strtoul (optarg, &end, 0); | |
204 | if (*end || link_info.stacksize < 0) | |
205 | einfo (_("%F%P: invalid stack size `%s'\''\n"), optarg + 11); | |
206 | if (!link_info.stacksize) | |
207 | /* Use -1 for explicit no-stack, because zero means | |
208 | 'default'. */ | |
209 | link_info.stacksize = -1; | |
210 | break; | |
211 | } | |
212 | case OPTION_LAZY_STACK: | |
213 | nto_lazy_stack = true; | |
214 | break; | |
215 | ' | |
216 | ||
217 | # Put these extra Neutrino routines in ld_${EMULATION_NAME}_emulation | |
218 | # | |
219 | ||
318d83e6 | 220 | LDEMUL_AFTER_OPEN=nto_after_open |