Home | History | Annotate | Line # | Download | only in emultempl
      1 # This shell script emits a C file. -*- C -*-
      2 #   Copyright (C) 2023-2025 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 source_em "${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 
     42 static asection*
     43 nto_create_QNX_note_section(int type)
     44 {
     45   asection *note_sec;
     46   flagword flags;
     47   Elf_External_Note *e_note;
     48   bfd_size_type size;
     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       fatal (_("%P: cannot create .note section in stub BFD.\n"));
     55       return NULL;
     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       fatal (_("%P: failed to create .note section\n"));
     64       return NULL;
     65     }
     66 
     67   size = offsetof (Elf_External_Note, name[sizeof "QNX"]);
     68   size = (size + 3) & -(bfd_size_type) 4;
     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);
     77   bfd_h_put_32 (stub_file->the_bfd, type, &e_note->type);
     78   memcpy (e_note->name, "QNX", sizeof "QNX");
     79 
     80   return note_sec;
     81 }
     82 
     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   bool duplicated_notes_detected = false;
     90   for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next)
     91     {
     92       Elf_External_Note *e_note;
     93       asection *sec;
     94 
     95       /* QNX notes are held under a note section simply named ".note".  */
     96       sec = bfd_get_section_by_name (abfd, ".note");
     97       if (!sec)
     98 	continue;
     99 
    100       /* Verify that this is a QNX note of the expected type.  */
    101       sec->contents = xmalloc(sec->size);
    102       if (!bfd_get_section_contents (sec->owner, sec, sec->contents, (file_ptr) 0,
    103 				     sec->size))
    104 	fatal (_("%P: %pB: can't read contents of section .note: %E\n"),
    105 	       sec->owner);
    106 
    107       e_note = (Elf_External_Note *) sec->contents;
    108       if (! strcmp("QNX", e_note->name) && *e_note->type == type)
    109 	{
    110 	  if (stack_note_sec)
    111 	    {
    112 	      if (!duplicated_notes_detected)
    113 		{
    114 		  einfo (_("%P: %pB: warning: duplicated QNX stack .note detected\n"),
    115 			 stack_note_sec->owner);
    116 		  duplicated_notes_detected = true;
    117 		}
    118 	      einfo (_("%P: %pB: warning: duplicated QNX stack .note detected\n"),
    119 		     sec->owner);
    120 	    }
    121 	  else
    122 	    {
    123 	      stack_note_sec = sec;
    124 	      /* Allow modification of this .note content.  */
    125 	      stack_note_sec->flags |= SEC_IN_MEMORY;
    126 	    }
    127 	}
    128     }
    129 
    130   if (stack_note_sec)
    131     return stack_note_sec;
    132   else
    133     return nto_create_QNX_note_section(type);
    134 
    135 }
    136 
    137 /* Generate the QNX stack .note section.  */
    138 static void
    139 nto_add_note_section (void) {
    140   asection *note_sec;
    141   struct nto_stack_note *n_note;
    142   bfd_size_type h_size;
    143   bool is_update = false;
    144 
    145   if (nto_lazy_stack && !link_info.stacksize)
    146     {
    147       fatal (_("%P: error: --lazy-stack must follow -zstack-size=<size>\n"));
    148       return;
    149     }
    150 
    151   /* Don't create a note if none of the stack parameter have to be modified.  */
    152   if (link_info.stacksize <= 0 && (link_info.execstack == link_info.noexecstack))
    153     return;
    154 
    155   note_sec = nto_lookup_QNX_note_section(QNT_STACK);
    156   if (! note_sec)
    157     return;
    158 
    159   /* Update QNX stack note content.  */
    160   h_size = note_sec->size - sizeof(struct nto_stack_note);
    161   n_note = (struct nto_stack_note *) (note_sec->contents + h_size);
    162   is_update = note_sec->owner != stub_file->the_bfd;
    163 
    164   if (link_info.stacksize > 0)
    165     bfd_h_put_32 (note_sec->owner, link_info.stacksize, &n_note->stacksize);
    166   else if (!is_update)
    167     bfd_h_put_32 (note_sec->owner, 0, &n_note->stacksize);
    168 
    169   if (nto_lazy_stack || (!is_update && link_info.stacksize <= 0))
    170     bfd_h_put_32 (note_sec->owner, 4096, &n_note->stackalloc);
    171   else if (link_info.stacksize > 0)
    172     bfd_h_put_32 (note_sec->owner, link_info.stacksize, &n_note->stackalloc);
    173 
    174   if (link_info.execstack)
    175     bfd_h_put_32 (note_sec->owner, 0, &n_note->execstack);
    176   else if (!is_update || link_info.noexecstack)
    177     bfd_h_put_32 (note_sec->owner, 1, &n_note->execstack);
    178 }
    179 
    180 static void
    181 nto_after_open (void)
    182 {
    183   nto_add_note_section();
    184   gld${EMULATION_NAME}_after_open ();
    185 }
    186 
    187 EOF
    188 
    189 # Define some shell vars to insert bits of code into the standard elf
    190 # parse_args and list_options functions.
    191 #
    192 
    193 PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
    194   { "stack", required_argument, NULL, OPTION_STACK },
    195   { "lazy-stack", no_argument, NULL, OPTION_LAZY_STACK },
    196 '
    197 
    198 PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'
    199   fprintf (file, _("\
    200   --stack <size>              Set size of the initial stack\n\
    201   --lazy-stack                Set lazy allocation of stack\n\
    202 "));
    203 '
    204 
    205 PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
    206     case OPTION_STACK:
    207       {
    208 	char *end;
    209 	link_info.stacksize = strtoul (optarg, &end, 0);
    210 	if (*end || link_info.stacksize < 0)
    211 	  fatal (_("%P: invalid stack size `%s'\''\n"), optarg + 11);
    212 	if (!link_info.stacksize)
    213 	  /* Use -1 for explicit no-stack, because zero means
    214 	     'default'.   */
    215 	  link_info.stacksize = -1;
    216 	break;
    217       }
    218     case OPTION_LAZY_STACK:
    219       nto_lazy_stack = true;
    220       break;
    221 '
    222 
    223 # Put these extra Neutrino routines in ld_${EMULATION_NAME}_emulation
    224 #
    225 
    226 LDEMUL_AFTER_OPEN=nto_after_open
    227