diff options
Diffstat (limited to 'ld/emultempl/nto.em')
-rw-r--r-- | ld/emultempl/nto.em | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/ld/emultempl/nto.em b/ld/emultempl/nto.em new file mode 100644 index 0000000..b38fddd --- /dev/null +++ b/ld/emultempl/nto.em @@ -0,0 +1,163 @@ +# This shell script emits a C file. -*- C -*- +# Copyright 2023 Free Software Foundation, Inc. +# +# This file is part of GLD, the Gnu Linker. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. +# + +# This file is sourced from elf.em, and defines extra Neutrino +# specific routines. + +# NTO templates aims to refine the default ${ARCH}elf.em template. +. "${srcdir}/emultempl/${ARCH}elf.em" + +cat >>e${EMULATION_NAME}.c <<EOF + +#include "elf/internal.h" +#include "elf/common.h" +#include "elf-bfd.h" +#include "../bfd/libbfd.h" + +bool nto_lazy_stack = false; +struct nto_stack_note +{ + unsigned char stacksize[4]; + unsigned char stackalloc[4]; + unsigned char execstack[4]; +}; + +/* Generate the QNT_STACK .note section. */ +static void +nto_add_note_section (void) { + asection *note_sec; + flagword flags; + Elf_External_Note *e_note; + bfd_size_type size, h_size; + struct nto_stack_note *n_note; + + /* Don't create a note if the stack size isn't provided. */ + if (link_info.stacksize <= 0) + return; + + /* As ${ARCH}elf.em is imported and ${ARCH}_elf_create_output_section_statements + is called before this function, stub_file should already be defined. */ + if (!stub_file) + { + einfo (_("%F%P: cannot create .note section in stub BFD.\n")); + return; + } + + if (nto_lazy_stack && !link_info.stacksize) + { + einfo (_("%F%P: error: --lazy-stack must follow -zstack-size=<size>\n")); + return; + } + + flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS + | SEC_IN_MEMORY | SEC_LINKER_CREATED); + note_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd, ".note", flags); + if (! note_sec) + { + einfo (_("%F%P: failed to create .note section\n")); + return; + } + + size = offsetof (Elf_External_Note, name[sizeof "QNX"]); + size = (size + 3) & -(bfd_size_type) 4; + h_size = size; + size += sizeof (struct nto_stack_note); + note_sec->size = size; + + elf_section_type (note_sec) = SHT_NOTE; + note_sec->contents = xmalloc (note_sec->size); + e_note = (Elf_External_Note *) note_sec->contents; + bfd_h_put_32 (stub_file->the_bfd, sizeof "QNX", &e_note->namesz); + bfd_h_put_32 (stub_file->the_bfd, sizeof (struct nto_stack_note), &e_note->descsz); + bfd_h_put_32 (stub_file->the_bfd, QNT_STACK, &e_note->type); + memcpy (e_note->name, "QNX", sizeof "QNX"); + + + /* Generate .note content.*/ + n_note = (struct nto_stack_note *) (note_sec->contents + h_size); + bfd_h_put_32 (stub_file->the_bfd, link_info.stacksize, &n_note->stacksize); + + if (nto_lazy_stack) + bfd_h_put_32 (stub_file->the_bfd, 4096, &n_note->stackalloc); + else + bfd_h_put_32 (stub_file->the_bfd, link_info.stacksize, &n_note->stackalloc); + + if (link_info.execstack != link_info.noexecstack && link_info.execstack) + bfd_h_put_32 (stub_file->the_bfd, 0, &n_note->execstack); + else + bfd_h_put_32 (stub_file->the_bfd, 1, &n_note->execstack); + +} + +static void +nto_create_output_section_statements (void) +{ + ${ARCH}_elf_create_output_section_statements (); + nto_add_note_section(); +} + +EOF + +# Define some shell vars to insert bits of code into the standard elf +# parse_args and list_options functions. +# + +PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}' +enum nto_options +{ + OPTION_STACK = 500, + OPTION_LAZY_STACK, +}; +' + +PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}' + { "stack", required_argument, NULL, OPTION_STACK }, + { "lazy-stack", no_argument, NULL, OPTION_LAZY_STACK }, +' + +PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}' + fprintf (file, _("\ + --stack <size> Set size of the initial stack\n\ + --lazy-stack Set lazy allocation of stack\n\ +")); +' + +PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' + case OPTION_STACK: + { + char *end; + link_info.stacksize = strtoul (optarg, &end, 0); + if (*end || link_info.stacksize < 0) + einfo (_("%F%P: invalid stack size `%s'\''\n"), optarg + 11); + if (!link_info.stacksize) + /* Use -1 for explicit no-stack, because zero means + 'default'. */ + link_info.stacksize = -1; + break; + } + case OPTION_LAZY_STACK: + nto_lazy_stack = true; + break; +' + +# Put these extra Neutrino routines in ld_${EMULATION_NAME}_emulation +# + +LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=nto_create_output_section_statements |