1# This shell script emits a C file. -*- C -*- 2# Copyright (C) 2023-2024 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 42static asection* 43nto_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 einfo (_("%F%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 einfo (_("%F%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. */ 84static asection* 85nto_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 einfo (_("%F%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. */ 138static void 139nto_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 einfo (_("%F%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 180static void 181nto_after_open (void) 182{ 183 nto_add_note_section(); 184 gld${EMULATION_NAME}_after_open (); 185} 186 187EOF 188 189# Define some shell vars to insert bits of code into the standard elf 190# parse_args and list_options functions. 191# 192 193PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}' 194enum nto_options 195{ 196 OPTION_STACK = 500, 197 OPTION_LAZY_STACK, 198}; 199' 200 201PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}' 202 { "stack", required_argument, NULL, OPTION_STACK }, 203 { "lazy-stack", no_argument, NULL, OPTION_LAZY_STACK }, 204' 205 206PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}' 207 fprintf (file, _("\ 208 --stack <size> Set size of the initial stack\n\ 209 --lazy-stack Set lazy allocation of stack\n\ 210")); 211' 212 213PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' 214 case OPTION_STACK: 215 { 216 char *end; 217 link_info.stacksize = strtoul (optarg, &end, 0); 218 if (*end || link_info.stacksize < 0) 219 einfo (_("%F%P: invalid stack size `%s'\''\n"), optarg + 11); 220 if (!link_info.stacksize) 221 /* Use -1 for explicit no-stack, because zero means 222 'default'. */ 223 link_info.stacksize = -1; 224 break; 225 } 226 case OPTION_LAZY_STACK: 227 nto_lazy_stack = true; 228 break; 229' 230 231# Put these extra Neutrino routines in ld_${EMULATION_NAME}_emulation 232# 233 234LDEMUL_AFTER_OPEN=nto_after_open 235