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