Subversion Repositories QNX 8.QNX8 GNU binutils

Rev

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