# This shell script emits a C file. -*- C -*- # Copyright (C) 2011-2014 Free Software Foundation, Inc. # # This file is part of the GNU Binutils. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, # MA 02110-1301, USA. # # This file is sourced from elf32.em, and defines extra C6X DSBT specific # features. # fragment <xvec == &tic6x_elf32_le_vec || link_info.output_bfd->xvec == &tic6x_elf32_be_vec || link_info.output_bfd->xvec == &tic6x_elf32_linux_le_vec || link_info.output_bfd->xvec == &tic6x_elf32_linux_be_vec || link_info.output_bfd->xvec == &tic6x_elf32_c6000_le_vec || link_info.output_bfd->xvec == &tic6x_elf32_c6000_be_vec); } /* Pass params to backend. */ static void tic6x_after_open (void) { if (is_tic6x_target ()) { if (params.dsbt_index >= params.dsbt_size) { einfo (_("%P%F: invalid --dsbt-index %d, outside DSBT size.\n"), params.dsbt_index); } elf32_tic6x_setup (&link_info, ¶ms); } gld${EMULATION_NAME}_after_open (); } static int compare_output_sec_vma (const void *a, const void *b) { asection *asec = *(asection **) a, *bsec = *(asection **) b; asection *aout = asec->output_section, *bout = bsec->output_section; bfd_vma avma, bvma; /* If there's no output section for some reason, compare equal. */ if (!aout || !bout) return 0; avma = aout->vma + asec->output_offset; bvma = bout->vma + bsec->output_offset; if (avma > bvma) return 1; else if (avma < bvma) return -1; return 0; } static void gld${EMULATION_NAME}_after_allocation (void) { int layout_changed = 0; int ret; if (!link_info.relocatable) { /* Build a sorted list of input text sections, then use that to process the unwind table index. */ unsigned int list_size = 10; asection **sec_list = (asection **) xmalloc (list_size * sizeof (asection *)); unsigned int sec_count = 0; LANG_FOR_EACH_INPUT_STATEMENT (is) { bfd *abfd = is->the_bfd; asection *sec; if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) continue; for (sec = abfd->sections; sec != NULL; sec = sec->next) { asection *out_sec = sec->output_section; if (out_sec && elf_section_data (sec) && elf_section_type (sec) == SHT_PROGBITS && (elf_section_flags (sec) & SHF_EXECINSTR) != 0 && (sec->flags & SEC_EXCLUDE) == 0 && sec->sec_info_type != SEC_INFO_TYPE_JUST_SYMS && out_sec != bfd_abs_section_ptr) { if (sec_count == list_size) { list_size *= 2; sec_list = (asection **) xrealloc (sec_list, list_size * sizeof (asection *)); } sec_list[sec_count++] = sec; } } } qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma); if (elf32_tic6x_fix_exidx_coverage (sec_list, sec_count, &link_info, merge_exidx_entries)) layout_changed = 1; free (sec_list); } /* bfd_elf32_discard_info just plays with debugging sections, ie. doesn't affect any code, so we can delay resizing the sections. */ ret = bfd_elf_discard_info (link_info.output_bfd, & link_info); if (ret < 0) { einfo ("%X%P: .eh_frame/.stab edit: %E\n"); return; } else if (ret > 0) layout_changed = 1; gld${EMULATION_NAME}_map_segments (layout_changed); } EOF # This code gets inserted into the generic elf32.sc linker script # and allows us to define our own command line switches. PARSE_AND_LIST_PROLOGUE=' #define OPTION_DSBT_INDEX 300 #define OPTION_DSBT_SIZE 301 #define OPTION_NO_MERGE_EXIDX_ENTRIES 302 ' PARSE_AND_LIST_LONGOPTS=' {"dsbt-index", required_argument, NULL, OPTION_DSBT_INDEX}, {"dsbt-size", required_argument, NULL, OPTION_DSBT_SIZE}, { "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES }, ' PARSE_AND_LIST_OPTIONS=' fprintf (file, _(" --dsbt-index \n")); fprintf (file, _("\t\t\tUse this as the DSBT index for the output object\n")); fprintf (file, _(" --dsbt-size \n")); fprintf (file, _("\t\t\tUse this as the number of entries in the DSBT table\n")); fprintf (file, _(" --no-merge-exidx-entries Disable merging exidx entries\n")); ' PARSE_AND_LIST_ARGS_CASES=' case OPTION_DSBT_INDEX: { char *end; params.dsbt_index = strtol (optarg, &end, 0); if (*end == 0 && params.dsbt_index >= 0 && params.dsbt_index < 0x7fff) break; einfo (_("%P%F: invalid --dsbt-index %s\n"), optarg); } break; case OPTION_DSBT_SIZE: { char *end; params.dsbt_size = strtol (optarg, &end, 0); if (*end == 0 && params.dsbt_size >= 0 && params.dsbt_size < 0x7fff) break; einfo (_("%P%F: invalid --dsbt-size %s\n"), optarg); } break; case OPTION_NO_MERGE_EXIDX_ENTRIES: merge_exidx_entries = 0; ' LDEMUL_AFTER_OPEN=tic6x_after_open LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation