]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - ld/emultempl/nto.em
ld: correctly handle QNX --lazy-stack without -zstack-size
[thirdparty/binutils-gdb.git] / ld / emultempl / nto.em
CommitLineData
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
27cat >>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
34bool nto_lazy_stack = false;
35struct nto_stack_note
36{
37 unsigned char stacksize[4];
38 unsigned char stackalloc[4];
39 unsigned char execstack[4];
40};
41
318d83e6
CC
42static asection*
43nto_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. */
84static asection*
85nto_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. */
124static void
125nto_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
166static void
318d83e6 167nto_after_open (void)
b1195129 168{
b1195129 169 nto_add_note_section();
318d83e6 170 gld${EMULATION_NAME}_after_open ();
b1195129
CC
171}
172
173EOF
174
175# Define some shell vars to insert bits of code into the standard elf
176# parse_args and list_options functions.
177#
178
179PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}'
180enum nto_options
181{
182 OPTION_STACK = 500,
183 OPTION_LAZY_STACK,
184};
185'
186
187PARSE_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
192PARSE_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
199PARSE_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 220LDEMUL_AFTER_OPEN=nto_after_open