| 1 | # This shell script emits a C file. -*- C -*-
|
|---|
| 2 | # Copyright 2000, 2001, 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|---|
| 19 | #
|
|---|
| 20 |
|
|---|
| 21 | # This file is sourced from elf32.em, and defines extra sh64
|
|---|
| 22 | # specific routines.
|
|---|
| 23 | #
|
|---|
| 24 |
|
|---|
| 25 | LDEMUL_AFTER_ALLOCATION=sh64_elf_${EMULATION_NAME}_after_allocation
|
|---|
| 26 | LDEMUL_BEFORE_ALLOCATION=sh64_elf_${EMULATION_NAME}_before_allocation
|
|---|
| 27 |
|
|---|
| 28 | cat >>e${EMULATION_NAME}.c <<EOF
|
|---|
| 29 |
|
|---|
| 30 | #include "libiberty.h"
|
|---|
| 31 | #include "libbfd.h"
|
|---|
| 32 | #include "elf-bfd.h"
|
|---|
| 33 | #include "elf/sh.h"
|
|---|
| 34 | #include "elf32-sh64.h"
|
|---|
| 35 |
|
|---|
| 36 | static void sh64_elf_${EMULATION_NAME}_before_allocation PARAMS ((void));
|
|---|
| 37 | static void sh64_elf_${EMULATION_NAME}_after_allocation PARAMS ((void));
|
|---|
| 38 |
|
|---|
| 39 | /* Check if we need a .cranges section and create it if it's not in any
|
|---|
| 40 | input file. It might seem better to always create it and if unneeded,
|
|---|
| 41 | discard it, but I don't find a simple way to discard it totally from
|
|---|
| 42 | the output.
|
|---|
| 43 |
|
|---|
| 44 | Putting it here instead of as a elf_backend_always_size_sections hook
|
|---|
| 45 | in elf32-sh64.c, means that we have access to linker command line
|
|---|
| 46 | options here, and we can access input sections in the order in which
|
|---|
| 47 | they will be linked. */
|
|---|
| 48 |
|
|---|
| 49 | static void
|
|---|
| 50 | sh64_elf_${EMULATION_NAME}_before_allocation ()
|
|---|
| 51 | {
|
|---|
| 52 | asection *cranges;
|
|---|
| 53 | asection *osec;
|
|---|
| 54 |
|
|---|
| 55 | /* Call main function; we're just extending it. */
|
|---|
| 56 | gld${EMULATION_NAME}_before_allocation ();
|
|---|
| 57 |
|
|---|
| 58 | cranges = bfd_get_section_by_name (output_bfd, SH64_CRANGES_SECTION_NAME);
|
|---|
| 59 |
|
|---|
| 60 | if (cranges != NULL)
|
|---|
| 61 | {
|
|---|
| 62 | if (command_line.relax)
|
|---|
| 63 | {
|
|---|
| 64 | /* FIXME: Look through incoming sections with .cranges
|
|---|
| 65 | descriptors, build up some kind of descriptors that the
|
|---|
| 66 | relaxing function will pick up and adjust, or perhaps make it
|
|---|
| 67 | find and adjust an associated .cranges descriptor. We could
|
|---|
| 68 | also look through incoming relocs and kill the ones marking
|
|---|
| 69 | relaxation areas, but that wouldn't be TRT. */
|
|---|
| 70 | einfo
|
|---|
| 71 | (_("%P: Sorry, turning off relaxing: .cranges section in input.\n"));
|
|---|
| 72 | einfo (_(" A .cranges section is present in:\n"));
|
|---|
| 73 |
|
|---|
| 74 | {
|
|---|
| 75 | LANG_FOR_EACH_INPUT_STATEMENT (f)
|
|---|
| 76 | {
|
|---|
| 77 | asection *input_cranges
|
|---|
| 78 | = bfd_get_section_by_name (f->the_bfd,
|
|---|
| 79 | SH64_CRANGES_SECTION_NAME);
|
|---|
| 80 | if (input_cranges != NULL)
|
|---|
| 81 | einfo (" %I\n", f);
|
|---|
| 82 | }
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | command_line.relax = FALSE;
|
|---|
| 86 | }
|
|---|
| 87 |
|
|---|
| 88 | /* We wouldn't need to do anything when there's already a .cranges
|
|---|
| 89 | section (and have a return here), except that we need to set the
|
|---|
| 90 | section flags right for output sections that *don't* need a
|
|---|
| 91 | .cranges section. */
|
|---|
| 92 | }
|
|---|
| 93 |
|
|---|
| 94 | if (command_line.relax)
|
|---|
| 95 | {
|
|---|
| 96 | LANG_FOR_EACH_INPUT_STATEMENT (f)
|
|---|
| 97 | {
|
|---|
| 98 | if (bfd_get_flavour (f->the_bfd) == bfd_target_elf_flavour)
|
|---|
| 99 | {
|
|---|
| 100 | asection *isec;
|
|---|
| 101 | for (isec = f->the_bfd->sections;
|
|---|
| 102 | isec != NULL;
|
|---|
| 103 | isec = isec->next)
|
|---|
| 104 | {
|
|---|
| 105 | if (elf_section_data (isec)->this_hdr.sh_flags
|
|---|
| 106 | & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
|
|---|
| 107 | {
|
|---|
| 108 | einfo (_("%P: Sorry, turning off relaxing: SHmedia sections present.\n"));
|
|---|
| 109 | einfo (" %I\n", f);
|
|---|
| 110 | command_line.relax = FALSE;
|
|---|
| 111 | goto done_scanning_shmedia_sections;
|
|---|
| 112 | }
|
|---|
| 113 | }
|
|---|
| 114 | }
|
|---|
| 115 | }
|
|---|
| 116 | }
|
|---|
| 117 | done_scanning_shmedia_sections:
|
|---|
| 118 |
|
|---|
| 119 | /* For each non-empty input section in each output section, check if it
|
|---|
| 120 | has the same SH64-specific flags. If some input section differs, we
|
|---|
| 121 | need a .cranges section. */
|
|---|
| 122 | for (osec = output_bfd->sections;
|
|---|
| 123 | osec != NULL;
|
|---|
| 124 | osec = osec->next)
|
|---|
| 125 | {
|
|---|
| 126 | struct sh64_section_data *sh64_sec_data;
|
|---|
| 127 | bfd_vma oflags_isa = 0;
|
|---|
| 128 | bfd_vma iflags_isa = 0;
|
|---|
| 129 |
|
|---|
| 130 | if (bfd_get_flavour (output_bfd) != bfd_target_elf_flavour)
|
|---|
| 131 | einfo (_("%FError: non-ELF output formats are not supported by this target's linker.\n"));
|
|---|
| 132 |
|
|---|
| 133 | sh64_sec_data = sh64_elf_section_data (osec)->sh64_info;
|
|---|
| 134 |
|
|---|
| 135 | /* Omit excluded or garbage-collected sections. */
|
|---|
| 136 | if (bfd_get_section_flags (output_bfd, osec) & SEC_EXCLUDE)
|
|---|
| 137 | continue;
|
|---|
| 138 |
|
|---|
| 139 | /* Make sure we have the target section data initialized. */
|
|---|
| 140 | if (sh64_sec_data == NULL)
|
|---|
| 141 | {
|
|---|
| 142 | sh64_sec_data = xcalloc (1, sizeof (struct sh64_section_data));
|
|---|
| 143 | sh64_elf_section_data (osec)->sh64_info = sh64_sec_data;
|
|---|
| 144 | }
|
|---|
| 145 |
|
|---|
| 146 | /* First find an input section so we have flags to compare with; the
|
|---|
| 147 | flags in the output section are not valid. */
|
|---|
| 148 | {
|
|---|
| 149 | LANG_FOR_EACH_INPUT_STATEMENT (f)
|
|---|
| 150 | {
|
|---|
| 151 | asection *isec;
|
|---|
| 152 |
|
|---|
| 153 | for (isec = f->the_bfd->sections;
|
|---|
| 154 | isec != NULL;
|
|---|
| 155 | isec = isec->next)
|
|---|
| 156 | {
|
|---|
| 157 | if (isec->output_section == osec
|
|---|
| 158 | && isec->_raw_size != 0
|
|---|
| 159 | && (bfd_get_section_flags (isec->owner, isec)
|
|---|
| 160 | & SEC_EXCLUDE) == 0)
|
|---|
| 161 | {
|
|---|
| 162 | oflags_isa
|
|---|
| 163 | = (elf_section_data (isec)->this_hdr.sh_flags
|
|---|
| 164 | & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
|
|---|
| 165 | goto break_1;
|
|---|
| 166 | }
|
|---|
| 167 | }
|
|---|
| 168 | }
|
|---|
| 169 | }
|
|---|
| 170 |
|
|---|
| 171 | break_1:
|
|---|
| 172 |
|
|---|
| 173 | /* Check that all input sections have the same contents-type flags
|
|---|
| 174 | as the first input section. */
|
|---|
| 175 | {
|
|---|
| 176 | LANG_FOR_EACH_INPUT_STATEMENT (f)
|
|---|
| 177 | {
|
|---|
| 178 | asection *isec;
|
|---|
| 179 |
|
|---|
| 180 | for (isec = f->the_bfd->sections;
|
|---|
| 181 | isec != NULL;
|
|---|
| 182 | isec = isec->next)
|
|---|
| 183 | {
|
|---|
| 184 | if (isec->output_section == osec
|
|---|
| 185 | && isec->_raw_size != 0
|
|---|
| 186 | && (bfd_get_section_flags (isec->owner, isec)
|
|---|
| 187 | & SEC_EXCLUDE) == 0)
|
|---|
| 188 | {
|
|---|
| 189 | iflags_isa
|
|---|
| 190 | = (elf_section_data (isec)->this_hdr.sh_flags
|
|---|
| 191 | & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
|
|---|
| 192 |
|
|---|
| 193 | /* If flags don't agree, we need a .cranges section.
|
|---|
| 194 | Create it here if it did not exist through input
|
|---|
| 195 | sections. */
|
|---|
| 196 | if (iflags_isa != oflags_isa)
|
|---|
| 197 | {
|
|---|
| 198 | if (cranges == NULL)
|
|---|
| 199 | {
|
|---|
| 200 | /* This section will be *appended* to
|
|---|
| 201 | sections, so the outer iteration will reach
|
|---|
| 202 | it in due time and set
|
|---|
| 203 | sh64_elf_section_data; no need to set it
|
|---|
| 204 | specifically here. */
|
|---|
| 205 | cranges
|
|---|
| 206 | = bfd_make_section (output_bfd,
|
|---|
| 207 | SH64_CRANGES_SECTION_NAME);
|
|---|
| 208 | if (cranges == NULL
|
|---|
| 209 | || !bfd_set_section_flags (output_bfd,
|
|---|
| 210 | cranges,
|
|---|
| 211 | SEC_LINKER_CREATED
|
|---|
| 212 | | SEC_KEEP
|
|---|
| 213 | | SEC_HAS_CONTENTS
|
|---|
| 214 | | SEC_DEBUGGING))
|
|---|
| 215 | einfo
|
|---|
| 216 | (_("%P%E%F: Can't make .cranges section\n"));
|
|---|
| 217 | }
|
|---|
| 218 |
|
|---|
| 219 | /* We don't need to look at more input sections,
|
|---|
| 220 | and we know this section will have mixed
|
|---|
| 221 | contents. */
|
|---|
| 222 | goto break_2;
|
|---|
| 223 | }
|
|---|
| 224 | }
|
|---|
| 225 | }
|
|---|
| 226 | }
|
|---|
| 227 | }
|
|---|
| 228 |
|
|---|
| 229 | /* If we got here, then all input sections in this output section
|
|---|
| 230 | have the same contents flag. Put that where we expect to see
|
|---|
| 231 | contents flags. We don't need to do this for sections that will
|
|---|
| 232 | need additional, linker-generated .cranges entries. */
|
|---|
| 233 | sh64_sec_data->contents_flags = iflags_isa;
|
|---|
| 234 |
|
|---|
| 235 | break_2:
|
|---|
| 236 | ;
|
|---|
| 237 | }
|
|---|
| 238 | }
|
|---|
| 239 |
|
|---|
| 240 | /* Size up and extend the .cranges section, merging generated entries. */
|
|---|
| 241 |
|
|---|
| 242 | static void
|
|---|
| 243 | sh64_elf_${EMULATION_NAME}_after_allocation ()
|
|---|
| 244 | {
|
|---|
| 245 | bfd_vma new_cranges = 0;
|
|---|
| 246 | bfd_vma cranges_growth = 0;
|
|---|
| 247 | asection *osec;
|
|---|
| 248 | bfd_byte *crangesp;
|
|---|
| 249 |
|
|---|
| 250 | asection *cranges
|
|---|
| 251 | = bfd_get_section_by_name (output_bfd, SH64_CRANGES_SECTION_NAME);
|
|---|
| 252 |
|
|---|
| 253 | /* If this ever starts doing something, we will pick it up. */
|
|---|
| 254 | after_allocation_default ();
|
|---|
| 255 |
|
|---|
| 256 | /* If there is no .cranges section, it is because it was seen earlier on
|
|---|
| 257 | that none was needed. Otherwise it must have been created then, or
|
|---|
| 258 | be present in input. */
|
|---|
| 259 | if (cranges == NULL)
|
|---|
| 260 | return;
|
|---|
| 261 |
|
|---|
| 262 | /* First, we set the ISA flags for each output section according to the
|
|---|
| 263 | first non-discarded section. For each input section in osec, we
|
|---|
| 264 | check if it has the same flags. If it does not, we set flags to mark
|
|---|
| 265 | a mixed section (and exit the loop early). */
|
|---|
| 266 | for (osec = output_bfd->sections;
|
|---|
| 267 | osec != NULL;
|
|---|
| 268 | osec = osec->next)
|
|---|
| 269 | {
|
|---|
| 270 | bfd_vma oflags_isa = 0;
|
|---|
| 271 | bfd_boolean need_check_cranges = FALSE;
|
|---|
| 272 |
|
|---|
| 273 | /* Omit excluded or garbage-collected sections. */
|
|---|
| 274 | if (bfd_get_section_flags (output_bfd, osec) & SEC_EXCLUDE)
|
|---|
| 275 | continue;
|
|---|
| 276 |
|
|---|
| 277 | /* First find an input section so we have flags to compare with; the
|
|---|
| 278 | flags in the output section are not valid. */
|
|---|
| 279 | {
|
|---|
| 280 | LANG_FOR_EACH_INPUT_STATEMENT (f)
|
|---|
| 281 | {
|
|---|
| 282 | asection *isec;
|
|---|
| 283 |
|
|---|
| 284 | for (isec = f->the_bfd->sections;
|
|---|
| 285 | isec != NULL;
|
|---|
| 286 | isec = isec->next)
|
|---|
| 287 | {
|
|---|
| 288 | if (isec->output_section == osec
|
|---|
| 289 | && isec->_raw_size != 0
|
|---|
| 290 | && (bfd_get_section_flags (isec->owner, isec)
|
|---|
| 291 | & SEC_EXCLUDE) == 0)
|
|---|
| 292 | {
|
|---|
| 293 | oflags_isa
|
|---|
| 294 | = (elf_section_data (isec)->this_hdr.sh_flags
|
|---|
| 295 | & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
|
|---|
| 296 | goto break_1;
|
|---|
| 297 | }
|
|---|
| 298 | }
|
|---|
| 299 | }
|
|---|
| 300 | }
|
|---|
| 301 |
|
|---|
| 302 | break_1:
|
|---|
| 303 |
|
|---|
| 304 | /* Check that all input sections have the same contents-type flags
|
|---|
| 305 | as the first input section. */
|
|---|
| 306 | {
|
|---|
| 307 | LANG_FOR_EACH_INPUT_STATEMENT (f)
|
|---|
| 308 | {
|
|---|
| 309 | asection *isec;
|
|---|
| 310 |
|
|---|
| 311 | for (isec = f->the_bfd->sections;
|
|---|
| 312 | isec != NULL;
|
|---|
| 313 | isec = isec->next)
|
|---|
| 314 | {
|
|---|
| 315 | if (isec->output_section == osec
|
|---|
| 316 | && isec->_raw_size != 0
|
|---|
| 317 | && (bfd_get_section_flags (isec->owner, isec)
|
|---|
| 318 | & SEC_EXCLUDE) == 0)
|
|---|
| 319 | {
|
|---|
| 320 | bfd_vma iflags_isa
|
|---|
| 321 | = (elf_section_data (isec)->this_hdr.sh_flags
|
|---|
| 322 | & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
|
|---|
| 323 |
|
|---|
| 324 | /* If flags don't agree, set the target-specific data
|
|---|
| 325 | of the section to mark that this section needs to
|
|---|
| 326 | be have .cranges section entries added. Don't
|
|---|
| 327 | bother setting ELF section flags in output section;
|
|---|
| 328 | they will be cleared later and will have to be
|
|---|
| 329 | re-initialized before the linked file is written. */
|
|---|
| 330 | if (iflags_isa != oflags_isa)
|
|---|
| 331 | {
|
|---|
| 332 | oflags_isa = SHF_SH5_ISA32_MIXED;
|
|---|
| 333 |
|
|---|
| 334 | BFD_ASSERT (sh64_elf_section_data (osec)->sh64_info);
|
|---|
| 335 |
|
|---|
| 336 | sh64_elf_section_data (osec)->sh64_info->contents_flags
|
|---|
| 337 | = SHF_SH5_ISA32_MIXED;
|
|---|
| 338 | need_check_cranges = TRUE;
|
|---|
| 339 | goto break_2;
|
|---|
| 340 | }
|
|---|
| 341 | }
|
|---|
| 342 | }
|
|---|
| 343 | }
|
|---|
| 344 | }
|
|---|
| 345 |
|
|---|
| 346 | break_2:
|
|---|
| 347 |
|
|---|
| 348 | /* If there were no new ranges for this output section, we don't
|
|---|
| 349 | need to iterate over the input sections to check how many are
|
|---|
| 350 | needed. */
|
|---|
| 351 | if (! need_check_cranges)
|
|---|
| 352 | continue;
|
|---|
| 353 |
|
|---|
| 354 | /* If we found a section with differing contents type, we need more
|
|---|
| 355 | ranges to mark the sections that are not mixed (and already have
|
|---|
| 356 | .cranges descriptors). Calculate the maximum number of new
|
|---|
| 357 | entries here. We may merge some of them, so that number is not
|
|---|
| 358 | final; it can shrink. */
|
|---|
| 359 | {
|
|---|
| 360 | LANG_FOR_EACH_INPUT_STATEMENT (f)
|
|---|
| 361 | {
|
|---|
| 362 | asection *isec;
|
|---|
| 363 |
|
|---|
| 364 | for (isec = f->the_bfd->sections;
|
|---|
| 365 | isec != NULL;
|
|---|
| 366 | isec = isec->next)
|
|---|
| 367 | {
|
|---|
| 368 | if (isec->output_section == osec
|
|---|
| 369 | && isec->_raw_size != 0
|
|---|
| 370 | && (bfd_get_section_flags (isec->owner, isec)
|
|---|
| 371 | & SEC_EXCLUDE) == 0
|
|---|
| 372 | && ((elf_section_data (isec)->this_hdr.sh_flags
|
|---|
| 373 | & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
|
|---|
| 374 | != SHF_SH5_ISA32_MIXED))
|
|---|
| 375 | new_cranges++;
|
|---|
| 376 | }
|
|---|
| 377 | }
|
|---|
| 378 | }
|
|---|
| 379 | }
|
|---|
| 380 |
|
|---|
| 381 | BFD_ASSERT (cranges->contents == NULL);
|
|---|
| 382 | BFD_ASSERT (sh64_elf_section_data (cranges)->sh64_info != NULL);
|
|---|
| 383 |
|
|---|
| 384 | /* Make sure we have .cranges in memory even if there were only
|
|---|
| 385 | assembler-generated .cranges. */
|
|---|
| 386 | cranges_growth = new_cranges * SH64_CRANGE_SIZE;
|
|---|
| 387 | cranges->contents
|
|---|
| 388 | = (bfd_byte *) xcalloc (cranges->_raw_size + cranges_growth, 1);
|
|---|
| 389 | bfd_set_section_flags (cranges->owner, cranges,
|
|---|
| 390 | bfd_get_section_flags (cranges->owner, cranges)
|
|---|
| 391 | | SEC_IN_MEMORY);
|
|---|
| 392 |
|
|---|
| 393 | /* If we don't need to grow the .cranges section beyond what was in the
|
|---|
| 394 | input sections, we have nothing more to do here. We then only got
|
|---|
| 395 | here because there was a .cranges section coming from input. Zero
|
|---|
| 396 | out the number of generated .cranges. */
|
|---|
| 397 | if (new_cranges == 0)
|
|---|
| 398 | {
|
|---|
| 399 | sh64_elf_section_data (cranges)->sh64_info->cranges_growth = 0;
|
|---|
| 400 | return;
|
|---|
| 401 | }
|
|---|
| 402 |
|
|---|
| 403 | crangesp = cranges->contents + cranges->_raw_size;
|
|---|
| 404 |
|
|---|
| 405 | /* Now pass over the sections again, and make reloc orders for the new
|
|---|
| 406 | .cranges entries. Constants are set as we go. */
|
|---|
| 407 | for (osec = output_bfd->sections;
|
|---|
| 408 | osec != NULL;
|
|---|
| 409 | osec = osec->next)
|
|---|
| 410 | {
|
|---|
| 411 | struct bfd_link_order *cr_addr_order = NULL;
|
|---|
| 412 | enum sh64_elf_cr_type last_cr_type = CRT_NONE;
|
|---|
| 413 | bfd_vma last_cr_size = 0;
|
|---|
| 414 | bfd_vma continuation_vma = 0;
|
|---|
| 415 |
|
|---|
| 416 | /* Omit excluded or garbage-collected sections, and output sections
|
|---|
| 417 | which were not marked as needing further processing. */
|
|---|
| 418 | if ((bfd_get_section_flags (output_bfd, osec) & SEC_EXCLUDE) != 0
|
|---|
| 419 | || (sh64_elf_section_data (osec)->sh64_info->contents_flags
|
|---|
| 420 | != SHF_SH5_ISA32_MIXED))
|
|---|
| 421 | continue;
|
|---|
| 422 |
|
|---|
| 423 | {
|
|---|
| 424 | LANG_FOR_EACH_INPUT_STATEMENT (f)
|
|---|
| 425 | {
|
|---|
| 426 | asection *isec;
|
|---|
| 427 |
|
|---|
| 428 | for (isec = f->the_bfd->sections;
|
|---|
| 429 | isec != NULL;
|
|---|
| 430 | isec = isec->next)
|
|---|
| 431 | {
|
|---|
| 432 | /* Allow only sections that have (at least initially) a
|
|---|
| 433 | non-zero size, and are not excluded, and are not marked
|
|---|
| 434 | as containing mixed data, thus already having .cranges
|
|---|
| 435 | entries. */
|
|---|
| 436 | if (isec->output_section == osec
|
|---|
| 437 | && isec->_raw_size != 0
|
|---|
| 438 | && (bfd_get_section_flags (isec->owner, isec)
|
|---|
| 439 | & SEC_EXCLUDE) == 0
|
|---|
| 440 | && ((elf_section_data (isec)->this_hdr.sh_flags
|
|---|
| 441 | & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
|
|---|
| 442 | != SHF_SH5_ISA32_MIXED))
|
|---|
| 443 | {
|
|---|
| 444 | enum sh64_elf_cr_type cr_type;
|
|---|
| 445 | bfd_vma cr_size;
|
|---|
| 446 | bfd_vma isa_flags
|
|---|
| 447 | = (elf_section_data (isec)->this_hdr.sh_flags
|
|---|
| 448 | & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
|
|---|
| 449 |
|
|---|
| 450 | if (isa_flags == SHF_SH5_ISA32)
|
|---|
| 451 | cr_type = CRT_SH5_ISA32;
|
|---|
| 452 | else if ((bfd_get_section_flags (isec->owner, isec)
|
|---|
| 453 | & SEC_CODE) == 0)
|
|---|
| 454 | cr_type = CRT_DATA;
|
|---|
| 455 | else
|
|---|
| 456 | cr_type = CRT_SH5_ISA16;
|
|---|
| 457 |
|
|---|
| 458 | cr_size
|
|---|
| 459 | = (isec->_cooked_size
|
|---|
| 460 | ? isec->_cooked_size : isec->_raw_size);
|
|---|
| 461 |
|
|---|
| 462 | /* Sections can be empty, like .text in a file that
|
|---|
| 463 | only contains other sections. Ranges shouldn't be
|
|---|
| 464 | emitted for them. This can presumably happen after
|
|---|
| 465 | relaxing and is not be caught at the "raw size"
|
|---|
| 466 | test above. */
|
|---|
| 467 | if (cr_size == 0)
|
|---|
| 468 | continue;
|
|---|
| 469 |
|
|---|
| 470 | /* See if this is a continuation of the previous range
|
|---|
| 471 | for the same output section. If so, just change
|
|---|
| 472 | the size of the last range and continue. */
|
|---|
| 473 | if (cr_type == last_cr_type
|
|---|
| 474 | && (continuation_vma
|
|---|
| 475 | == osec->vma + isec->output_offset))
|
|---|
| 476 | {
|
|---|
| 477 | last_cr_size += cr_size;
|
|---|
| 478 | bfd_put_32 (output_bfd, last_cr_size,
|
|---|
| 479 | crangesp - SH64_CRANGE_SIZE
|
|---|
| 480 | + SH64_CRANGE_CR_SIZE_OFFSET);
|
|---|
| 481 |
|
|---|
| 482 | continuation_vma += cr_size;
|
|---|
| 483 | continue;
|
|---|
| 484 | }
|
|---|
| 485 |
|
|---|
| 486 | /* If we emit relocateable contents, we need a
|
|---|
| 487 | relocation for the start address. */
|
|---|
| 488 | if (link_info.relocateable || link_info.emitrelocations)
|
|---|
| 489 | {
|
|---|
| 490 | /* FIXME: We could perhaps use lang_add_reloc and
|
|---|
| 491 | friends here, but I'm not really sure that
|
|---|
| 492 | would leave us free to do some optimizations
|
|---|
| 493 | later. */
|
|---|
| 494 | cr_addr_order
|
|---|
| 495 | = bfd_new_link_order (output_bfd, cranges);
|
|---|
| 496 |
|
|---|
| 497 | if (cr_addr_order == NULL)
|
|---|
| 498 | {
|
|---|
| 499 | einfo (_("%P%F: bfd_new_link_order failed\n"));
|
|---|
| 500 | return;
|
|---|
| 501 | }
|
|---|
| 502 |
|
|---|
| 503 | cr_addr_order->type = bfd_section_reloc_link_order;
|
|---|
| 504 | cr_addr_order->offset
|
|---|
| 505 | = (cranges->output_offset
|
|---|
| 506 | + crangesp + SH64_CRANGE_CR_ADDR_OFFSET
|
|---|
| 507 | - cranges->contents);
|
|---|
| 508 | cr_addr_order->size = 4;
|
|---|
| 509 | cr_addr_order->u.reloc.p
|
|---|
| 510 | = ((struct bfd_link_order_reloc *)
|
|---|
| 511 | xmalloc (sizeof (struct bfd_link_order_reloc)));
|
|---|
| 512 |
|
|---|
| 513 | cr_addr_order->u.reloc.p->reloc = BFD_RELOC_32;
|
|---|
| 514 | cr_addr_order->u.reloc.p->u.section = osec;
|
|---|
| 515 |
|
|---|
| 516 | /* Since SH, unlike normal RELA-targets, uses a
|
|---|
| 517 | "partial inplace" REL-like relocation for this,
|
|---|
| 518 | we put the addend in the contents and specify 0
|
|---|
| 519 | for the reloc. */
|
|---|
| 520 | bfd_put_32 (output_bfd, isec->output_offset,
|
|---|
| 521 | crangesp + SH64_CRANGE_CR_ADDR_OFFSET);
|
|---|
| 522 | cr_addr_order->u.reloc.p->addend = 0;
|
|---|
| 523 |
|
|---|
| 524 | /* We must update the number of relocations here,
|
|---|
| 525 | since the elf linker does not take link orders
|
|---|
| 526 | into account when setting header sizes. The
|
|---|
| 527 | actual relocation orders are however executed
|
|---|
| 528 | correctly. */
|
|---|
| 529 | elf_section_data(cranges)->rel_count++;
|
|---|
| 530 | }
|
|---|
| 531 | else
|
|---|
| 532 | bfd_put_32 (output_bfd,
|
|---|
| 533 | osec->vma + isec->output_offset,
|
|---|
| 534 | crangesp + SH64_CRANGE_CR_ADDR_OFFSET);
|
|---|
| 535 |
|
|---|
| 536 | /* If we could make a reloc for cr_size we would do
|
|---|
| 537 | it, but we would have to have a symbol for the size
|
|---|
| 538 | of the _input_ section and there's no way to
|
|---|
| 539 | generate that. */
|
|---|
| 540 | bfd_put_32 (output_bfd, cr_size,
|
|---|
| 541 | crangesp + SH64_CRANGE_CR_SIZE_OFFSET);
|
|---|
| 542 |
|
|---|
| 543 | bfd_put_16 (output_bfd, (bfd_vma) cr_type,
|
|---|
| 544 | crangesp + SH64_CRANGE_CR_TYPE_OFFSET);
|
|---|
| 545 |
|
|---|
| 546 | last_cr_type = cr_type;
|
|---|
| 547 | last_cr_size = cr_size;
|
|---|
| 548 | continuation_vma
|
|---|
| 549 | = osec->vma + isec->output_offset + cr_size;
|
|---|
| 550 | crangesp += SH64_CRANGE_SIZE;
|
|---|
| 551 | }
|
|---|
| 552 | }
|
|---|
| 553 | }
|
|---|
| 554 | }
|
|---|
| 555 | }
|
|---|
| 556 |
|
|---|
| 557 | /* The .cranges section will have this size, no larger or smaller.
|
|---|
| 558 | Since relocs (if relocateable linking) will be emitted into the
|
|---|
| 559 | "extended" size, we must set the raw size to the total. We have to
|
|---|
| 560 | keep track of the number of new .cranges entries.
|
|---|
| 561 |
|
|---|
| 562 | Sorting before writing is done by sh64_elf_final_write_processing. */
|
|---|
| 563 |
|
|---|
| 564 | cranges->_cooked_size = crangesp - cranges->contents;
|
|---|
| 565 | sh64_elf_section_data (cranges)->sh64_info->cranges_growth
|
|---|
| 566 | = cranges->_cooked_size - cranges->_raw_size;
|
|---|
| 567 | cranges->_raw_size = cranges->_cooked_size;
|
|---|
| 568 | }
|
|---|