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 |