Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
19 | pmbaty | 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 | # Pierre-Marie Baty -- yep, but with one exception: if ARCH is i386 or x86_64, the emulation file is elf-x86.em instead |
||
26 | if [ "${ARCH}" = "i386" ] || [ "${ARCH}" = "x86_64" ]; then |
||
27 | . "${srcdir}/emultempl/elf-x86.em" |
||
28 | |||
29 | cat >>e${EMULATION_NAME}.c <<EOF |
||
30 | |||
31 | #include "elf/internal.h" |
||
32 | #include "elf/common.h" |
||
33 | #include "elf-bfd.h" |
||
34 | #include "../bfd/libbfd.h" |
||
35 | |||
36 | bool nto_lazy_stack = false; |
||
37 | struct nto_stack_note |
||
38 | { |
||
39 | unsigned char stacksize[4]; |
||
40 | unsigned char stackalloc[4]; |
||
41 | unsigned char execstack[4]; |
||
42 | }; |
||
43 | |||
44 | static asection* |
||
45 | nto_create_QNX_note_section(int type) |
||
46 | { |
||
47 | asection *note_sec; |
||
48 | flagword flags; |
||
49 | Elf_External_Note *e_note; |
||
50 | bfd_size_type size; |
||
51 | |||
52 | /* Pierre-Marie Baty -- this is only called if no .note section already exists |
||
53 | in the input BFDs. So just create one in the first one of the list. |
||
54 | And NORMALLY this doesn't break anything. */ |
||
55 | |||
56 | flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS |
||
57 | | SEC_IN_MEMORY | SEC_LINKER_CREATED); |
||
58 | note_sec = bfd_make_section_anyway_with_flags (link_info.input_bfds, ".note", flags); |
||
59 | if (! note_sec) |
||
60 | { |
||
61 | einfo (_("%F%P: failed to create .note section\n")); |
||
62 | return NULL; |
||
63 | } |
||
64 | |||
65 | size = offsetof (Elf_External_Note, name[sizeof "QNX"]); |
||
66 | size = (size + 3) & -(bfd_size_type) 4; |
||
67 | size += sizeof (struct nto_stack_note); |
||
68 | note_sec->size = size; |
||
69 | |||
70 | elf_section_type (note_sec) = SHT_NOTE; |
||
71 | note_sec->contents = xmalloc (note_sec->size); |
||
72 | e_note = (Elf_External_Note *) note_sec->contents; |
||
73 | bfd_h_put_32 (link_info.input_bfds, sizeof "QNX", &e_note->namesz); |
||
74 | bfd_h_put_32 (link_info.input_bfds, sizeof (struct nto_stack_note), &e_note->descsz); |
||
75 | bfd_h_put_32 (link_info.input_bfds, type, &e_note->type); |
||
76 | memcpy (e_note->name, "QNX", sizeof "QNX"); |
||
77 | |||
78 | return note_sec; |
||
79 | } |
||
80 | |||
81 | /* Lookup for a section holding a QNX note or create a new section. */ |
||
82 | static asection* |
||
83 | nto_lookup_QNX_note_section(int type) |
||
84 | { |
||
85 | asection *stack_note_sec = NULL; |
||
86 | bfd *abfd; |
||
87 | bool duplicated_notes_detected = false; |
||
88 | for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next) |
||
89 | { |
||
90 | Elf_External_Note *e_note; |
||
91 | asection *sec; |
||
92 | |||
93 | /* QNX notes are held under a note section simply named ".note". */ |
||
94 | sec = bfd_get_section_by_name (abfd, ".note"); |
||
95 | if (!sec) |
||
96 | continue; |
||
97 | |||
98 | /* Verify that this is a QNX note of the expected type. */ |
||
99 | sec->contents = xmalloc(sec->size); |
||
100 | if (!bfd_get_section_contents (sec->owner, sec, sec->contents, (file_ptr) 0, |
||
101 | sec->size)) |
||
102 | einfo (_("%F%P: %pB: can't read contents of section .note: %E\n"), |
||
103 | sec->owner); |
||
104 | |||
105 | e_note = (Elf_External_Note *) sec->contents; |
||
106 | if (! strcmp("QNX", e_note->name) && *e_note->type == type) |
||
107 | { |
||
108 | if (stack_note_sec) |
||
109 | { |
||
110 | if (!duplicated_notes_detected) |
||
111 | { |
||
112 | einfo (_("%P: %pB: warning: duplicated QNX stack .note detected\n"), |
||
113 | stack_note_sec->owner); |
||
114 | duplicated_notes_detected = true; |
||
115 | } |
||
116 | einfo (_("%P: %pB: warning: duplicated QNX stack .note detected\n"), |
||
117 | sec->owner); |
||
118 | } |
||
119 | else |
||
120 | { |
||
121 | stack_note_sec = sec; |
||
122 | /* Allow modification of this .note content. */ |
||
123 | stack_note_sec->flags |= SEC_IN_MEMORY; |
||
124 | } |
||
125 | } |
||
126 | } |
||
127 | |||
128 | if (stack_note_sec) |
||
129 | return stack_note_sec; |
||
130 | else |
||
131 | return nto_create_QNX_note_section(type); |
||
132 | |||
133 | } |
||
134 | |||
135 | /* Generate the QNX stack .note section. */ |
||
136 | static void |
||
137 | nto_add_note_section (void) { |
||
138 | asection *note_sec; |
||
139 | struct nto_stack_note *n_note; |
||
140 | bfd_size_type h_size; |
||
141 | bool is_update = false; |
||
142 | |||
143 | if (nto_lazy_stack && !link_info.stacksize) |
||
144 | { |
||
145 | einfo (_("%F%P: error: --lazy-stack must follow -zstack-size=<size>\n")); |
||
146 | return; |
||
147 | } |
||
148 | |||
149 | /* Don't create a note if none of the stack parameter have to be modified. */ |
||
150 | if (link_info.stacksize <= 0 && (link_info.execstack == link_info.noexecstack)) |
||
151 | return; |
||
152 | |||
153 | note_sec = nto_lookup_QNX_note_section(QNT_STACK); |
||
154 | if (! note_sec) |
||
155 | return; |
||
156 | |||
157 | /* Update QNX stack note content. */ |
||
158 | h_size = note_sec->size - sizeof(struct nto_stack_note); |
||
159 | n_note = (struct nto_stack_note *) (note_sec->contents + h_size); |
||
160 | is_update = note_sec->owner != NULL; /* Pierre-Marie Baty -- was comparing against a stub file's BFD, which doesn't exist in x86 */ |
||
161 | |||
162 | if (link_info.stacksize > 0) |
||
163 | bfd_h_put_32 (note_sec->owner, link_info.stacksize, &n_note->stacksize); |
||
164 | else if (!is_update) |
||
165 | bfd_h_put_32 (note_sec->owner, 0, &n_note->stacksize); |
||
166 | |||
167 | if (nto_lazy_stack || (!is_update && link_info.stacksize <= 0)) |
||
168 | bfd_h_put_32 (note_sec->owner, 4096, &n_note->stackalloc); |
||
169 | else if (link_info.stacksize > 0) |
||
170 | bfd_h_put_32 (note_sec->owner, link_info.stacksize, &n_note->stackalloc); |
||
171 | |||
172 | if (link_info.execstack) |
||
173 | bfd_h_put_32 (note_sec->owner, 0, &n_note->execstack); |
||
174 | else if (!is_update || link_info.noexecstack) |
||
175 | bfd_h_put_32 (note_sec->owner, 1, &n_note->execstack); |
||
176 | } |
||
177 | |||
178 | static void |
||
179 | nto_after_open (void) |
||
180 | { |
||
181 | nto_add_note_section(); |
||
182 | gld${EMULATION_NAME}_after_open (); |
||
183 | } |
||
184 | |||
185 | EOF |
||
186 | else |
||
187 | # Pierre-Marie Baty -- anything else (not i386 nor x86_64) |
||
188 | . "${srcdir}/emultempl/${ARCH}elf.em" |
||
189 | |||
190 | cat >>e${EMULATION_NAME}.c <<EOF |
||
191 | |||
192 | #include "elf/internal.h" |
||
193 | #include "elf/common.h" |
||
194 | #include "elf-bfd.h" |
||
195 | #include "../bfd/libbfd.h" |
||
196 | |||
197 | bool nto_lazy_stack = false; |
||
198 | struct nto_stack_note |
||
199 | { |
||
200 | unsigned char stacksize[4]; |
||
201 | unsigned char stackalloc[4]; |
||
202 | unsigned char execstack[4]; |
||
203 | }; |
||
204 | |||
205 | static asection* |
||
206 | nto_create_QNX_note_section(int type) |
||
207 | { |
||
208 | asection *note_sec; |
||
209 | flagword flags; |
||
210 | Elf_External_Note *e_note; |
||
211 | bfd_size_type size; |
||
212 | |||
213 | /* As ${ARCH}elf.em is imported and ${ARCH}_elf_create_output_section_statements |
||
214 | is called before this function, stub_file should already be defined. */ |
||
215 | if (!stub_file) |
||
216 | { |
||
217 | einfo (_("%F%P: cannot create .note section in stub BFD.\n")); |
||
218 | return NULL; |
||
219 | } |
||
220 | |||
221 | flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS |
||
222 | | SEC_IN_MEMORY | SEC_LINKER_CREATED); |
||
223 | note_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd, ".note", flags); |
||
224 | if (! note_sec) |
||
225 | { |
||
226 | einfo (_("%F%P: failed to create .note section\n")); |
||
227 | return NULL; |
||
228 | } |
||
229 | |||
230 | size = offsetof (Elf_External_Note, name[sizeof "QNX"]); |
||
231 | size = (size + 3) & -(bfd_size_type) 4; |
||
232 | size += sizeof (struct nto_stack_note); |
||
233 | note_sec->size = size; |
||
234 | |||
235 | elf_section_type (note_sec) = SHT_NOTE; |
||
236 | note_sec->contents = xmalloc (note_sec->size); |
||
237 | e_note = (Elf_External_Note *) note_sec->contents; |
||
238 | bfd_h_put_32 (stub_file->the_bfd, sizeof "QNX", &e_note->namesz); |
||
239 | bfd_h_put_32 (stub_file->the_bfd, sizeof (struct nto_stack_note), &e_note->descsz); |
||
240 | bfd_h_put_32 (stub_file->the_bfd, type, &e_note->type); |
||
241 | memcpy (e_note->name, "QNX", sizeof "QNX"); |
||
242 | |||
243 | return note_sec; |
||
244 | } |
||
245 | |||
246 | /* Lookup for a section holding a QNX note or create a new section. */ |
||
247 | static asection* |
||
248 | nto_lookup_QNX_note_section(int type) |
||
249 | { |
||
250 | asection *stack_note_sec = NULL; |
||
251 | bfd *abfd; |
||
252 | bool duplicated_notes_detected = false; |
||
253 | for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next) |
||
254 | { |
||
255 | Elf_External_Note *e_note; |
||
256 | asection *sec; |
||
257 | |||
258 | /* QNX notes are held under a note section simply named ".note". */ |
||
259 | sec = bfd_get_section_by_name (abfd, ".note"); |
||
260 | if (!sec) |
||
261 | continue; |
||
262 | |||
263 | /* Verify that this is a QNX note of the expected type. */ |
||
264 | sec->contents = xmalloc(sec->size); |
||
265 | if (!bfd_get_section_contents (sec->owner, sec, sec->contents, (file_ptr) 0, |
||
266 | sec->size)) |
||
267 | einfo (_("%F%P: %pB: can't read contents of section .note: %E\n"), |
||
268 | sec->owner); |
||
269 | |||
270 | e_note = (Elf_External_Note *) sec->contents; |
||
271 | if (! strcmp("QNX", e_note->name) && *e_note->type == type) |
||
272 | { |
||
273 | if (stack_note_sec) |
||
274 | { |
||
275 | if (!duplicated_notes_detected) |
||
276 | { |
||
277 | einfo (_("%P: %pB: warning: duplicated QNX stack .note detected\n"), |
||
278 | stack_note_sec->owner); |
||
279 | duplicated_notes_detected = true; |
||
280 | } |
||
281 | einfo (_("%P: %pB: warning: duplicated QNX stack .note detected\n"), |
||
282 | sec->owner); |
||
283 | } |
||
284 | else |
||
285 | { |
||
286 | stack_note_sec = sec; |
||
287 | /* Allow modification of this .note content. */ |
||
288 | stack_note_sec->flags |= SEC_IN_MEMORY; |
||
289 | } |
||
290 | } |
||
291 | } |
||
292 | |||
293 | if (stack_note_sec) |
||
294 | return stack_note_sec; |
||
295 | else |
||
296 | return nto_create_QNX_note_section(type); |
||
297 | |||
298 | } |
||
299 | |||
300 | /* Generate the QNX stack .note section. */ |
||
301 | static void |
||
302 | nto_add_note_section (void) { |
||
303 | asection *note_sec; |
||
304 | struct nto_stack_note *n_note; |
||
305 | bfd_size_type h_size; |
||
306 | bool is_update = false; |
||
307 | |||
308 | if (nto_lazy_stack && !link_info.stacksize) |
||
309 | { |
||
310 | einfo (_("%F%P: error: --lazy-stack must follow -zstack-size=<size>\n")); |
||
311 | return; |
||
312 | } |
||
313 | |||
314 | /* Don't create a note if none of the stack parameter have to be modified. */ |
||
315 | if (link_info.stacksize <= 0 && (link_info.execstack == link_info.noexecstack)) |
||
316 | return; |
||
317 | |||
318 | note_sec = nto_lookup_QNX_note_section(QNT_STACK); |
||
319 | if (! note_sec) |
||
320 | return; |
||
321 | |||
322 | /* Update QNX stack note content. */ |
||
323 | h_size = note_sec->size - sizeof(struct nto_stack_note); |
||
324 | n_note = (struct nto_stack_note *) (note_sec->contents + h_size); |
||
325 | is_update = note_sec->owner != stub_file->the_bfd; |
||
326 | |||
327 | if (link_info.stacksize > 0) |
||
328 | bfd_h_put_32 (note_sec->owner, link_info.stacksize, &n_note->stacksize); |
||
329 | else if (!is_update) |
||
330 | bfd_h_put_32 (note_sec->owner, 0, &n_note->stacksize); |
||
331 | |||
332 | if (nto_lazy_stack || (!is_update && link_info.stacksize <= 0)) |
||
333 | bfd_h_put_32 (note_sec->owner, 4096, &n_note->stackalloc); |
||
334 | else if (link_info.stacksize > 0) |
||
335 | bfd_h_put_32 (note_sec->owner, link_info.stacksize, &n_note->stackalloc); |
||
336 | |||
337 | if (link_info.execstack) |
||
338 | bfd_h_put_32 (note_sec->owner, 0, &n_note->execstack); |
||
339 | else if (!is_update || link_info.noexecstack) |
||
340 | bfd_h_put_32 (note_sec->owner, 1, &n_note->execstack); |
||
341 | } |
||
342 | |||
343 | static void |
||
344 | nto_after_open (void) |
||
345 | { |
||
346 | nto_add_note_section(); |
||
347 | gld${EMULATION_NAME}_after_open (); |
||
348 | } |
||
349 | |||
350 | EOF |
||
351 | fi |
||
352 | |||
353 | # Define some shell vars to insert bits of code into the standard elf |
||
354 | # parse_args and list_options functions. |
||
355 | # |
||
356 | |||
357 | PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}' |
||
358 | enum nto_options |
||
359 | { |
||
360 | OPTION_STACK = 500, |
||
361 | OPTION_LAZY_STACK, |
||
362 | }; |
||
363 | ' |
||
364 | |||
365 | PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}' |
||
366 | { "stack", required_argument, NULL, OPTION_STACK }, |
||
367 | { "lazy-stack", no_argument, NULL, OPTION_LAZY_STACK }, |
||
368 | ' |
||
369 | |||
370 | PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}' |
||
371 | fprintf (file, _("\ |
||
372 | --stack <size> Set size of the initial stack\n\ |
||
373 | --lazy-stack Set lazy allocation of stack\n\ |
||
374 | ")); |
||
375 | ' |
||
376 | |||
377 | PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' |
||
378 | case OPTION_STACK: |
||
379 | { |
||
380 | char *end; |
||
381 | link_info.stacksize = strtoul (optarg, &end, 0); |
||
382 | if (*end || link_info.stacksize < 0) |
||
383 | einfo (_("%F%P: invalid stack size `%s'\''\n"), optarg + 11); |
||
384 | if (!link_info.stacksize) |
||
385 | /* Use -1 for explicit no-stack, because zero means |
||
386 | 'default'. */ |
||
387 | link_info.stacksize = -1; |
||
388 | break; |
||
389 | } |
||
390 | case OPTION_LAZY_STACK: |
||
391 | nto_lazy_stack = true; |
||
392 | break; |
||
393 | ' |
||
394 | |||
395 | # Put these extra Neutrino routines in ld_${EMULATION_NAME}_emulation |
||
396 | # |
||
397 | |||
398 | # Pierre-Marie Baty -- hook changed to accomodate this patch: https://inbox.sourceware.org/binutils/20231013080248.219837-1-chigot@adacore.com/T/#u |
||
399 | LDEMUL_AFTER_OPEN=nto_after_open |