Home | History | Annotate | Line # | Download | only in emultempl
beos.em revision 1.1.1.8
      1      1.1  christos # This shell script emits a C file. -*- C -*-
      2      1.1  christos # It does some substitutions.
      3      1.1  christos if [ -z "$MACHINE" ]; then
      4      1.1  christos   OUTPUT_ARCH=${ARCH}
      5      1.1  christos else
      6      1.1  christos   OUTPUT_ARCH=${ARCH}:${MACHINE}
      7      1.1  christos fi
      8      1.1  christos fragment <<EOF
      9      1.1  christos /* This file is part of GLD, the Gnu Linker.
     10  1.1.1.8  christos    Copyright (C) 1995-2025 Free Software Foundation, Inc.
     11      1.1  christos 
     12      1.1  christos    This file is part of the GNU Binutils.
     13      1.1  christos 
     14      1.1  christos    This program is free software; you can redistribute it and/or modify
     15      1.1  christos    it under the terms of the GNU General Public License as published by
     16      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     17      1.1  christos    (at your option) any later version.
     18      1.1  christos 
     19      1.1  christos    This program is distributed in the hope that it will be useful,
     20      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     21      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     22      1.1  christos    GNU General Public License for more details.
     23      1.1  christos 
     24      1.1  christos    You should have received a copy of the GNU General Public License
     25      1.1  christos    along with this program; if not, write to the Free Software
     26      1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     27      1.1  christos    MA 02110-1301, USA.  */
     28      1.1  christos 
     29      1.1  christos 
     30      1.1  christos /* For WINDOWS_NT */
     31      1.1  christos /* The original file generated returned different default scripts depending
     32      1.1  christos    on whether certain switches were set, but these switches pertain to the
     33      1.1  christos    Linux system and that particular version of coff.  In the NT case, we
     34      1.1  christos    only determine if the subsystem is console or windows in order to select
     35      1.1  christos    the correct entry point by default. */
     36      1.1  christos 
     37      1.1  christos #include "sysdep.h"
     38      1.1  christos #include "bfd.h"
     39      1.1  christos #include "bfdlink.h"
     40  1.1.1.5  christos #include "ctf-api.h"
     41      1.1  christos #include "getopt.h"
     42      1.1  christos #include "libiberty.h"
     43      1.1  christos #include "filenames.h"
     44      1.1  christos #include "ld.h"
     45      1.1  christos #include "ldmain.h"
     46      1.1  christos #include "ldexp.h"
     47      1.1  christos #include "ldlang.h"
     48      1.1  christos #include "ldfile.h"
     49      1.1  christos #include "ldemul.h"
     50      1.1  christos #include <ldgram.h>
     51      1.1  christos #include "ldlex.h"
     52      1.1  christos #include "ldmisc.h"
     53      1.1  christos #include "ldctor.h"
     54      1.1  christos #include "coff/internal.h"
     55      1.1  christos #include "../bfd/libcoff.h"
     56      1.1  christos 
     57      1.1  christos #define TARGET_IS_${EMULATION_NAME}
     58      1.1  christos 
     59      1.1  christos static struct internal_extra_pe_aouthdr pe;
     60      1.1  christos static int dll;
     61      1.1  christos 
     62      1.1  christos extern const char *output_filename;
     63      1.1  christos 
     64      1.1  christos static void
     65  1.1.1.6  christos gld${EMULATION_NAME}_before_parse (void)
     66      1.1  christos {
     67      1.1  christos   ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
     68      1.1  christos   output_filename = "a.exe";
     69      1.1  christos }
     70      1.1  christos 
     72      1.1  christos /* PE format extra command line options.  */
     73      1.1  christos 
     74      1.1  christos static void
     75      1.1  christos gld${EMULATION_NAME}_add_options
     76      1.1  christos   (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl,
     77      1.1  christos    struct option **longopts, int nrl ATTRIBUTE_UNUSED,
     78      1.1  christos    struct option **really_longopts ATTRIBUTE_UNUSED)
     79      1.1  christos {
     80      1.1  christos   static const struct option xtra_long[] = {
     81      1.1  christos     /* PE options */
     82      1.1  christos     {"base-file", required_argument, NULL, OPTION_BASE_FILE},
     83      1.1  christos     {"dll", no_argument, NULL, OPTION_DLL},
     84      1.1  christos     {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
     85      1.1  christos     {"heap", required_argument, NULL, OPTION_HEAP},
     86      1.1  christos     {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
     87      1.1  christos     {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
     88      1.1  christos     {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
     89      1.1  christos     {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
     90      1.1  christos     {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
     91      1.1  christos     {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
     92      1.1  christos     {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
     93      1.1  christos     {"stack", required_argument, NULL, OPTION_STACK},
     94      1.1  christos     {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
     95      1.1  christos     {NULL, no_argument, NULL, 0}
     96      1.1  christos   };
     97      1.1  christos 
     98      1.1  christos   *longopts = (struct option *)
     99      1.1  christos     xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
    100      1.1  christos   memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
    101      1.1  christos }
    102      1.1  christos 
    103      1.1  christos 
    104      1.1  christos /* PE/WIN32; added routines to get the subsystem type, heap and/or stack
    105      1.1  christos    parameters which may be input from the command line */
    106      1.1  christos 
    107      1.1  christos typedef struct {
    108      1.1  christos   void *ptr;
    109      1.1  christos   int size;
    110      1.1  christos   int value;
    111      1.1  christos   char *symbol;
    112      1.1  christos   int inited;
    113      1.1  christos } definfo;
    114      1.1  christos 
    115      1.1  christos #define D(field,symbol,def)  {&pe.field,sizeof(pe.field), def, symbol,0}
    116      1.1  christos 
    117      1.1  christos static definfo init[] =
    118      1.1  christos {
    119      1.1  christos   /* imagebase must be first */
    120      1.1  christos #define IMAGEBASEOFF 0
    121      1.1  christos   D(ImageBase,"__image_base__", BEOS_EXE_IMAGE_BASE),
    122      1.1  christos #define DLLOFF 1
    123      1.1  christos   {&dll, sizeof(dll), 0, "__dll__", 0},
    124      1.1  christos   D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
    125      1.1  christos   D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
    126      1.1  christos   D(MajorOperatingSystemVersion,"__major_os_version__", 4),
    127      1.1  christos   D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
    128      1.1  christos   D(MajorImageVersion,"__major_image_version__", 1),
    129      1.1  christos   D(MinorImageVersion,"__minor_image_version__", 0),
    130      1.1  christos   D(MajorSubsystemVersion,"__major_subsystem_version__", 4),
    131      1.1  christos   D(MinorSubsystemVersion,"__minor_subsystem_version__", 0),
    132      1.1  christos   D(Subsystem,"__subsystem__", 3),
    133      1.1  christos   D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x2000000),
    134      1.1  christos   D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
    135      1.1  christos   D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
    136      1.1  christos   D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
    137      1.1  christos   D(LoaderFlags,"__loader_flags__", 0x0),
    138      1.1  christos   { NULL, 0, 0, NULL, 0 }
    139      1.1  christos };
    140      1.1  christos 
    141      1.1  christos 
    142      1.1  christos static void
    143      1.1  christos set_pe_name (char *name, long val)
    144      1.1  christos {
    145      1.1  christos   int i;
    146      1.1  christos   /* Find the name and set it. */
    147      1.1  christos   for (i = 0; init[i].ptr; i++)
    148      1.1  christos     {
    149      1.1  christos       if (strcmp (name, init[i].symbol) == 0)
    150      1.1  christos 	{
    151      1.1  christos 	  init[i].value = val;
    152      1.1  christos 	  init[i].inited = 1;
    153      1.1  christos 	  return;
    154      1.1  christos 	}
    155      1.1  christos     }
    156      1.1  christos   abort();
    157      1.1  christos }
    158      1.1  christos 
    159      1.1  christos 
    160      1.1  christos static void
    161      1.1  christos set_pe_subsystem (void)
    162      1.1  christos {
    163      1.1  christos   const char *sver;
    164      1.1  christos   int len;
    165      1.1  christos   int i;
    166      1.1  christos   static const struct
    167      1.1  christos     {
    168      1.1  christos       const char *name;
    169      1.1  christos       const int value;
    170      1.1  christos       const char *entry;
    171      1.1  christos     }
    172      1.1  christos   v[] =
    173      1.1  christos     {
    174      1.1  christos       { "native", 1, "_NtProcessStartup" },
    175      1.1  christos       { "windows", 2, "_WinMainCRTStartup" },
    176      1.1  christos       { "wwindows", 2, "_wWinMainCRTStartup" },
    177      1.1  christos       { "console", 3, "_mainCRTStartup" },
    178      1.1  christos       { "wconsole", 3, "_wmainCRTStartup" },
    179      1.1  christos       { "posix", 7, "___PosixProcessStartup"},
    180      1.1  christos       { 0, 0, 0 }
    181      1.1  christos     };
    182      1.1  christos 
    183      1.1  christos   sver = strchr (optarg, ':');
    184      1.1  christos   if (sver == NULL)
    185      1.1  christos     len = strlen (optarg);
    186      1.1  christos   else
    187      1.1  christos     {
    188      1.1  christos       char *end;
    189      1.1  christos 
    190      1.1  christos       len = sver - optarg;
    191      1.1  christos       set_pe_name ("__major_subsystem_version__",
    192      1.1  christos 		   strtoul (sver + 1, &end, 0));
    193      1.1  christos       if (*end == '.')
    194      1.1  christos 	set_pe_name ("__minor_subsystem_version__",
    195      1.1  christos 		     strtoul (end + 1, &end, 0));
    196  1.1.1.4  christos       if (*end != '\0')
    197      1.1  christos 	einfo (_("%P: warning: bad version number in -subsystem option\n"));
    198      1.1  christos     }
    199      1.1  christos 
    200      1.1  christos   for (i = 0; v[i].name; i++)
    201      1.1  christos     {
    202      1.1  christos       if (strncmp (optarg, v[i].name, len) == 0
    203      1.1  christos 	  && v[i].name[len] == '\0')
    204      1.1  christos 	{
    205      1.1  christos 	  set_pe_name ("__subsystem__", v[i].value);
    206      1.1  christos 
    207      1.1  christos 	  /* If the subsystem is windows, we use a different entry
    208      1.1  christos 	     point.  */
    209      1.1  christos 	  lang_default_entry (v[i].entry);
    210      1.1  christos 
    211      1.1  christos 	  return;
    212      1.1  christos 	}
    213  1.1.1.8  christos     }
    214      1.1  christos   fatal (_("%P: invalid subsystem type %s\n"), optarg);
    215      1.1  christos }
    216      1.1  christos 
    217      1.1  christos 
    218      1.1  christos static void
    219      1.1  christos set_pe_value (char *name)
    220      1.1  christos {
    221      1.1  christos   char *end;
    222      1.1  christos   set_pe_name (name,  strtoul (optarg, &end, 0));
    223  1.1.1.8  christos   if (end == optarg)
    224      1.1  christos     fatal (_("%P: invalid hex number for PE parameter '%s'\n"), optarg);
    225      1.1  christos 
    226      1.1  christos   optarg = end;
    227      1.1  christos }
    228      1.1  christos 
    229      1.1  christos static void
    230      1.1  christos set_pe_stack_heap (char *resname, char *comname)
    231      1.1  christos {
    232      1.1  christos   set_pe_value (resname);
    233      1.1  christos   if (*optarg == ',')
    234      1.1  christos     {
    235      1.1  christos       optarg++;
    236      1.1  christos       set_pe_value (comname);
    237      1.1  christos     }
    238  1.1.1.8  christos   else if (*optarg)
    239      1.1  christos     fatal (_("%P: strange hex info for PE parameter '%s'\n"), optarg);
    240      1.1  christos }
    241      1.1  christos 
    242  1.1.1.6  christos 
    243      1.1  christos static bool
    244      1.1  christos gld${EMULATION_NAME}_handle_option (int optc)
    245      1.1  christos {
    246      1.1  christos   switch (optc)
    247      1.1  christos     {
    248  1.1.1.6  christos     default:
    249      1.1  christos       return false;
    250      1.1  christos 
    251      1.1  christos     case OPTION_BASE_FILE:
    252      1.1  christos       link_info.base_file = fopen (optarg, FOPEN_WB);
    253  1.1.1.8  christos       if (link_info.base_file == NULL)
    254      1.1  christos 	fatal (_("%P: cannot open base file %s\n"), optarg);
    255      1.1  christos       break;
    256      1.1  christos 
    257      1.1  christos       /* PE options */
    258      1.1  christos     case OPTION_HEAP:
    259      1.1  christos       set_pe_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
    260      1.1  christos       break;
    261      1.1  christos     case OPTION_STACK:
    262      1.1  christos       set_pe_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
    263      1.1  christos       break;
    264      1.1  christos     case OPTION_SUBSYSTEM:
    265      1.1  christos       set_pe_subsystem ();
    266      1.1  christos       break;
    267      1.1  christos     case OPTION_MAJOR_OS_VERSION:
    268      1.1  christos       set_pe_value ("__major_os_version__");
    269      1.1  christos       break;
    270      1.1  christos     case OPTION_MINOR_OS_VERSION:
    271      1.1  christos       set_pe_value ("__minor_os_version__");
    272      1.1  christos       break;
    273      1.1  christos     case OPTION_MAJOR_SUBSYSTEM_VERSION:
    274      1.1  christos       set_pe_value ("__major_subsystem_version__");
    275      1.1  christos       break;
    276      1.1  christos     case OPTION_MINOR_SUBSYSTEM_VERSION:
    277      1.1  christos       set_pe_value ("__minor_subsystem_version__");
    278      1.1  christos       break;
    279      1.1  christos     case OPTION_MAJOR_IMAGE_VERSION:
    280      1.1  christos       set_pe_value ("__major_image_version__");
    281      1.1  christos       break;
    282      1.1  christos     case OPTION_MINOR_IMAGE_VERSION:
    283      1.1  christos       set_pe_value ("__minor_image_version__");
    284      1.1  christos       break;
    285      1.1  christos     case OPTION_FILE_ALIGNMENT:
    286      1.1  christos       set_pe_value ("__file_alignment__");
    287      1.1  christos       break;
    288      1.1  christos     case OPTION_SECTION_ALIGNMENT:
    289      1.1  christos       set_pe_value ("__section_alignment__");
    290      1.1  christos       break;
    291      1.1  christos     case OPTION_DLL:
    292      1.1  christos       set_pe_name ("__dll__", 1);
    293      1.1  christos       break;
    294      1.1  christos     case OPTION_IMAGE_BASE:
    295      1.1  christos       set_pe_value ("__image_base__");
    296      1.1  christos       break;
    297  1.1.1.6  christos     }
    298      1.1  christos   return true;
    299      1.1  christos }
    300      1.1  christos 
    302      1.1  christos /* Assign values to the special symbols before the linker script is
    303      1.1  christos    read.  */
    304  1.1.1.6  christos 
    305      1.1  christos static void
    306      1.1  christos gld${EMULATION_NAME}_set_symbols (void)
    307      1.1  christos {
    308      1.1  christos   /* Run through and invent symbols for all the
    309      1.1  christos      names and insert the defaults. */
    310      1.1  christos   int j;
    311      1.1  christos 
    312  1.1.1.2  christos   if (!init[IMAGEBASEOFF].inited)
    313      1.1  christos     {
    314      1.1  christos       if (bfd_link_relocatable (&link_info))
    315      1.1  christos 	init[IMAGEBASEOFF].value = 0;
    316      1.1  christos       else if (init[DLLOFF].value)
    317      1.1  christos 	init[IMAGEBASEOFF].value = BEOS_DLL_IMAGE_BASE;
    318      1.1  christos       else
    319      1.1  christos 	init[IMAGEBASEOFF].value = BEOS_EXE_IMAGE_BASE;
    320      1.1  christos     }
    321  1.1.1.2  christos 
    322      1.1  christos   /* Don't do any symbol assignments if this is a relocatable link.  */
    323      1.1  christos   if (bfd_link_relocatable (&link_info))
    324      1.1  christos     return;
    325      1.1  christos 
    326      1.1  christos   /* Glue the assignments into the abs section */
    327      1.1  christos   push_stat_ptr (&abs_output_section->children);
    328      1.1  christos 
    329      1.1  christos   for (j = 0; init[j].ptr; j++)
    330      1.1  christos     {
    331  1.1.1.6  christos       long val = init[j].value;
    332      1.1  christos       lang_add_assignment (exp_assign (init[j].symbol, exp_intop (val),
    333      1.1  christos 				       false));
    334      1.1  christos       if (init[j].size == sizeof(short))
    335      1.1  christos 	*(short *)init[j].ptr = val;
    336      1.1  christos       else if (init[j].size == sizeof(int))
    337      1.1  christos 	*(int *)init[j].ptr = val;
    338      1.1  christos       else if (init[j].size == sizeof(long))
    339      1.1  christos 	*(long *)init[j].ptr = val;
    340      1.1  christos       /* This might be a long long or other special type.  */
    341      1.1  christos       else if (init[j].size == sizeof(bfd_vma))
    342      1.1  christos 	*(bfd_vma *)init[j].ptr = val;
    343      1.1  christos       else	abort();
    344      1.1  christos     }
    345      1.1  christos   /* Restore the pointer. */
    346      1.1  christos   pop_stat_ptr ();
    347      1.1  christos 
    348      1.1  christos   if (pe.FileAlignment >
    349  1.1.1.4  christos       pe.SectionAlignment)
    350      1.1  christos     {
    351      1.1  christos       einfo (_("%P: warning, file alignment > section alignment\n"));
    352      1.1  christos     }
    353      1.1  christos }
    354  1.1.1.6  christos 
    355      1.1  christos static void
    356      1.1  christos gld${EMULATION_NAME}_after_open (void)
    357      1.1  christos {
    358      1.1  christos   after_open_default ();
    359      1.1  christos 
    360      1.1  christos   /* Pass the wacky PE command line options into the output bfd.
    361  1.1.1.7  christos      FIXME: This should be done via a function, rather than by
    362  1.1.1.8  christos      including an internal BFD header.  */
    363      1.1  christos   if (!obj_pe (link_info.output_bfd))
    364      1.1  christos     fatal (_("%P: PE operations on non PE file\n"));
    365      1.1  christos 
    366      1.1  christos   pe_data(link_info.output_bfd)->pe_opthdr = pe;
    367      1.1  christos   pe_data(link_info.output_bfd)->dll = init[DLLOFF].value;
    368      1.1  christos 
    369      1.1  christos }
    370      1.1  christos 
    372      1.1  christos /* Callback functions for qsort in sort_sections. */
    373      1.1  christos 
    374  1.1.1.5  christos static int
    375  1.1.1.5  christos sort_by_file_name (const void *a, const void *b)
    376  1.1.1.5  christos {
    377  1.1.1.5  christos   const lang_input_section_type *const *ra = a;
    378      1.1  christos   const lang_input_section_type *const *rb = b;
    379      1.1  christos   asection *sa = (*ra)->section;
    380  1.1.1.6  christos   asection *sb = (*rb)->section;
    381  1.1.1.6  christos   int i, a_sec, b_sec;
    382      1.1  christos 
    383      1.1  christos   i = filename_cmp (bfd_get_filename (sa->owner->my_archive),
    384      1.1  christos 		    bfd_get_filename (sb->owner->my_archive));
    385  1.1.1.6  christos   if (i != 0)
    386  1.1.1.6  christos     return i;
    387      1.1  christos 
    388      1.1  christos   i = filename_cmp (bfd_get_filename (sa->owner),
    389      1.1  christos 		    bfd_get_filename (sb->owner));
    390      1.1  christos   if (i != 0)
    391      1.1  christos     return i;
    392      1.1  christos   /* the tail idata4/5 are the only ones without relocs to an
    393      1.1  christos      idata$6 section unless we are importing by ordinal,
    394      1.1  christos      so sort them to last to terminate the IAT
    395  1.1.1.5  christos      and HNT properly. if no reloc this one is import by ordinal
    396      1.1  christos      so we have to sort by section contents */
    397  1.1.1.5  christos 
    398  1.1.1.4  christos   if (sa->reloc_count + sb->reloc_count != 0)
    399  1.1.1.4  christos     {
    400      1.1  christos       i = sa->reloc_count > sb->reloc_count ? -1 : 0;
    401  1.1.1.5  christos       if (i != 0)
    402      1.1  christos 	return i;
    403      1.1  christos 
    404      1.1  christos       return sa->reloc_count > sb->reloc_count ? 0 : 1;
    405  1.1.1.4  christos     }
    406  1.1.1.5  christos   else
    407  1.1.1.4  christos     {
    408  1.1.1.4  christos       /* don't sort .idata$6 or .idata$7 FIXME dlltool eliminate .idata$7 */
    409  1.1.1.5  christos       if ((strcmp (sa->name, ".idata$6") == 0))
    410  1.1.1.5  christos 	return 0;
    411  1.1.1.8  christos 
    412  1.1.1.5  christos       if (!bfd_get_section_contents (sa->owner, sa, &a_sec, (file_ptr) 0,
    413  1.1.1.4  christos 				     (bfd_size_type) sizeof (a_sec)))
    414  1.1.1.5  christos 	fatal (_("%P: %pB: can't read contents of section .idata: %E\n"),
    415  1.1.1.5  christos 	       sa->owner);
    416  1.1.1.8  christos 
    417  1.1.1.5  christos       if (!bfd_get_section_contents (sb->owner, sb, &b_sec, (file_ptr) 0,
    418  1.1.1.4  christos 				     (bfd_size_type) sizeof (b_sec)))
    419  1.1.1.4  christos 	fatal (_("%P: %pB: can't read contents of section .idata: %E\n"),
    420  1.1.1.4  christos 	       sb->owner);
    421  1.1.1.4  christos 
    422  1.1.1.4  christos       i = a_sec < b_sec ? -1 : 0;
    423  1.1.1.4  christos       if (i != 0)
    424  1.1.1.4  christos 	return i;
    425      1.1  christos       return a_sec < b_sec ? 0 : 1;
    426      1.1  christos     }
    427      1.1  christos   return 0;
    428      1.1  christos }
    429      1.1  christos 
    430  1.1.1.5  christos static int
    431  1.1.1.5  christos sort_by_section_name (const void *a, const void *b)
    432  1.1.1.5  christos {
    433  1.1.1.5  christos   const lang_input_section_type *const *ra = a;
    434      1.1  christos   const lang_input_section_type *const *rb = b;
    435  1.1.1.5  christos   const char *sna = (*ra)->section->name;
    436      1.1  christos   const char *snb = (*rb)->section->name;
    437      1.1  christos   int i;
    438      1.1  christos   i = strcmp (sna, snb);
    439      1.1  christos   /* This is a hack to make .stab and .stabstr last, so we don't have
    440      1.1  christos      to fix strip/objcopy for .reloc sections.
    441  1.1.1.6  christos      FIXME stripping images with a .rsrc section still needs to be fixed.  */
    442  1.1.1.6  christos   if (i != 0)
    443  1.1.1.4  christos     {
    444      1.1  christos       if ((startswith (sna, ".stab"))
    445      1.1  christos 	  && (!startswith (snb, ".stab")))
    446      1.1  christos 	return 1;
    447      1.1  christos     }
    448      1.1  christos   return i;
    449      1.1  christos }
    450      1.1  christos 
    451      1.1  christos /* Subroutine of sort_sections to a contiguous subset of a list of sections.
    452      1.1  christos    NEXT_AFTER is the element after the last one to sort.
    453      1.1  christos    The result is a pointer to the last element's "next" pointer.  */
    454      1.1  christos 
    455      1.1  christos static lang_statement_union_type **
    456      1.1  christos sort_sections_1 (lang_statement_union_type **startptr,
    457      1.1  christos 		 lang_statement_union_type *next_after,
    458      1.1  christos 		 int count,
    459      1.1  christos 		 int (*sort_func) (const void *, const void *))
    460      1.1  christos {
    461      1.1  christos   lang_statement_union_type **vec;
    462      1.1  christos   lang_statement_union_type *p;
    463      1.1  christos   int i;
    464      1.1  christos   lang_statement_union_type **ret;
    465      1.1  christos 
    466      1.1  christos   if (count == 0)
    467      1.1  christos     return startptr;
    468      1.1  christos 
    469      1.1  christos   vec = ((lang_statement_union_type **)
    470      1.1  christos 	 xmalloc (count * sizeof (lang_statement_union_type *)));
    471      1.1  christos 
    472      1.1  christos   for (p = *startptr, i = 0; i < count; i++, p = p->header.next)
    473      1.1  christos     vec[i] = p;
    474      1.1  christos 
    475      1.1  christos   qsort (vec, count, sizeof (vec[0]), sort_func);
    476      1.1  christos 
    477      1.1  christos   /* Fill in the next pointers again. */
    478      1.1  christos   *startptr = vec[0];
    479      1.1  christos   for (i = 0; i < count - 1; i++)
    480      1.1  christos     vec[i]->header.next = vec[i + 1];
    481      1.1  christos   vec[i]->header.next = next_after;
    482      1.1  christos   ret = &vec[i]->header.next;
    483      1.1  christos   free (vec);
    484      1.1  christos   return ret;
    485      1.1  christos }
    486      1.1  christos 
    487      1.1  christos /* Sort the .idata\$foo input sections of archives into filename order.
    488      1.1  christos    The reason is so dlltool can arrange to have the pe dll import information
    489      1.1  christos    generated correctly - the head of the list goes into dh.o, the tail into
    490      1.1  christos    dt.o, and the guts into ds[nnnn].o.  Note that this is only needed for the
    491      1.1  christos    .idata section.
    492      1.1  christos    FIXME: This may no longer be necessary with grouped sections.  Instead of
    493      1.1  christos    sorting on dh.o, ds[nnnn].o, dt.o, one could, for example, have dh.o use
    494      1.1  christos    .idata\$4h, have ds[nnnn].o use .idata\$4s[nnnn], and have dt.o use .idata\$4t.
    495      1.1  christos    This would have to be elaborated upon to handle multiple dll's
    496      1.1  christos    [assuming such an eloboration is possible of course].
    497      1.1  christos 
    498      1.1  christos    We also sort sections in '\$' wild statements.  These are created by the
    499      1.1  christos    place_orphans routine to implement grouped sections.  */
    500      1.1  christos 
    501      1.1  christos static void
    502      1.1  christos sort_sections (lang_statement_union_type *s)
    503      1.1  christos {
    504      1.1  christos   for (; s ; s = s->header.next)
    505      1.1  christos     switch (s->header.type)
    506      1.1  christos       {
    507      1.1  christos       case lang_output_section_statement_enum:
    508      1.1  christos 	sort_sections (s->output_section_statement.children.head);
    509      1.1  christos 	break;
    510      1.1  christos       case lang_wild_statement_enum:
    511      1.1  christos 	{
    512      1.1  christos 	  lang_statement_union_type **p = &s->wild_statement.children.head;
    513      1.1  christos 	  struct wildcard_list *sec;
    514      1.1  christos 
    515      1.1  christos 	  for (sec = s->wild_statement.section_list; sec; sec = sec->next)
    516  1.1.1.6  christos 	    {
    517      1.1  christos 	      /* Is this the .idata section?  */
    518      1.1  christos 	      if (sec->spec.name != NULL
    519      1.1  christos 		  && startswith (sec->spec.name, ".idata"))
    520      1.1  christos 		{
    521      1.1  christos 		  /* Sort the children.  We want to sort any objects in
    522      1.1  christos 		     the same archive.  In order to handle the case of
    523      1.1  christos 		     including a single archive multiple times, we sort
    524      1.1  christos 		     all the children by archive name and then by object
    525      1.1  christos 		     name.  After sorting them, we re-thread the pointer
    526      1.1  christos 		     chain.  */
    527      1.1  christos 
    528      1.1  christos 		  while (*p)
    529      1.1  christos 		    {
    530      1.1  christos 		      lang_statement_union_type *start = *p;
    531      1.1  christos 		      if (start->header.type != lang_input_section_enum
    532      1.1  christos 			  || !start->input_section.section->owner->my_archive)
    533      1.1  christos 			p = &(start->header.next);
    534      1.1  christos 		      else
    535      1.1  christos 			{
    536      1.1  christos 			  lang_statement_union_type *end;
    537      1.1  christos 			  int count;
    538      1.1  christos 
    539      1.1  christos 			  for (end = start, count = 0;
    540      1.1  christos 			       end && (end->header.type
    541      1.1  christos 				       == lang_input_section_enum);
    542      1.1  christos 			       end = end->header.next)
    543      1.1  christos 			    count++;
    544      1.1  christos 
    545      1.1  christos 			  p = sort_sections_1 (p, end, count,
    546      1.1  christos 					       sort_by_file_name);
    547      1.1  christos 			}
    548      1.1  christos 		    }
    549      1.1  christos 		  break;
    550      1.1  christos 		}
    551      1.1  christos 
    552      1.1  christos 	      /* If this is a collection of grouped sections, sort them.
    553      1.1  christos 		 The linker script must explicitly mention "*(.foo\$)" or
    554      1.1  christos 		 "*(.foo\$*)".  Don't sort them if \$ is not the last
    555      1.1  christos 		 character (not sure if this is really useful, but it
    556      1.1  christos 		 allows explicitly mentioning some \$ sections and letting
    557      1.1  christos 		 the linker handle the rest).  */
    558      1.1  christos 	      if (sec->spec.name != NULL)
    559      1.1  christos 		{
    560      1.1  christos 		  char *q = strchr (sec->spec.name, '\$');
    561      1.1  christos 
    562      1.1  christos 		  if (q != NULL
    563      1.1  christos 		      && (q[1] == '\0'
    564      1.1  christos 			  || (q[1] == '*' && q[2] == '\0')))
    565      1.1  christos 		    {
    566      1.1  christos 		      lang_statement_union_type *end;
    567      1.1  christos 		      int count;
    568      1.1  christos 
    569      1.1  christos 		      for (end = *p, count = 0; end; end = end->header.next)
    570      1.1  christos 			{
    571      1.1  christos 			  if (end->header.type != lang_input_section_enum)
    572      1.1  christos 			    abort ();
    573      1.1  christos 			  count++;
    574      1.1  christos 			}
    575      1.1  christos 		      (void) sort_sections_1 (p, end, count,
    576      1.1  christos 					      sort_by_section_name);
    577      1.1  christos 		    }
    578      1.1  christos 		  break;
    579      1.1  christos 		}
    580      1.1  christos 	    }
    581      1.1  christos 	}
    582      1.1  christos 	break;
    583      1.1  christos       default:
    584      1.1  christos 	break;
    585      1.1  christos       }
    586  1.1.1.6  christos }
    587      1.1  christos 
    588      1.1  christos static void
    589      1.1  christos gld${EMULATION_NAME}_before_allocation (void)
    590      1.1  christos {
    591      1.1  christos #ifdef TARGET_IS_armpe
    592      1.1  christos   /* FIXME: we should be able to set the size of the interworking stub
    593      1.1  christos      section.
    594      1.1  christos 
    595      1.1  christos      Here we rummage through the found bfds to collect glue
    596      1.1  christos      information.  FIXME: should this be based on a command line
    597  1.1.1.4  christos      option?  krk (a] cygnus.com */
    598  1.1.1.4  christos   {
    599  1.1.1.4  christos     LANG_FOR_EACH_INPUT_STATEMENT (is)
    600  1.1.1.4  christos     {
    601  1.1.1.4  christos       if (!arm_process_before_allocation (is->the_bfd, & link_info))
    602  1.1.1.4  christos 	{
    603  1.1.1.4  christos 	  einfo (_("%P: errors encountered processing file %s\n"),
    604      1.1  christos 		 is->filename);
    605      1.1  christos 	}
    606      1.1  christos     }
    607      1.1  christos   }
    608      1.1  christos 
    609      1.1  christos   /* We have seen it all. Allocate it, and carry on */
    610      1.1  christos   arm_allocate_interworking_sections (& link_info);
    611      1.1  christos #endif /* TARGET_IS_armpe */
    612      1.1  christos 
    613      1.1  christos   sort_sections (stat_ptr->head);
    614      1.1  christos 
    615      1.1  christos   before_allocation_default ();
    616      1.1  christos }
    617      1.1  christos 
    619      1.1  christos /* Place an orphan section.  We use this to put sections with a '\$' in them
    620      1.1  christos    into the right place.  Any section with a '\$' in them (e.g. .text\$foo)
    621      1.1  christos    gets mapped to the output section with everything from the '\$' on stripped
    622      1.1  christos    (e.g. .text).
    623      1.1  christos    See the Microsoft Portable Executable and Common Object File Format
    624      1.1  christos    Specification 4.1, section 4.2, Grouped Sections.
    625      1.1  christos 
    626      1.1  christos    FIXME: This is now handled by the linker script using wildcards,
    627      1.1  christos    but I'm leaving this here in case we want to enable it for sections
    628      1.1  christos    which are not mentioned in the linker script.  */
    629      1.1  christos 
    630      1.1  christos static lang_output_section_statement_type *
    631      1.1  christos gld${EMULATION_NAME}_place_orphan (asection *s,
    632      1.1  christos 				   const char *secname,
    633      1.1  christos 				   int constraint)
    634      1.1  christos {
    635      1.1  christos   char *output_secname, *ps;
    636      1.1  christos   lang_output_section_statement_type *os;
    637      1.1  christos   lang_statement_union_type *l;
    638      1.1  christos 
    639      1.1  christos   if ((s->flags & SEC_ALLOC) == 0)
    640      1.1  christos     return NULL;
    641      1.1  christos 
    642  1.1.1.2  christos   /* Don't process grouped sections unless doing a final link.
    643      1.1  christos      If they're marked as COMDAT sections, we don't want .text\$foo to
    644      1.1  christos      end up in .text and then have .text disappear because it's marked
    645      1.1  christos      link-once-discard.  */
    646      1.1  christos   if (bfd_link_relocatable (&link_info))
    647      1.1  christos     return NULL;
    648  1.1.1.8  christos 
    649      1.1  christos   /* Everything from the '\$' on gets deleted so don't allow '\$' as the
    650      1.1  christos      first character.  */
    651      1.1  christos   if (*secname == '\$')
    652      1.1  christos     fatal (_("%P: section %s has '\$' as first character\n"), secname);
    653      1.1  christos   if (strchr (secname + 1, '\$') == NULL)
    654      1.1  christos     return NULL;
    655      1.1  christos 
    656      1.1  christos   /* Look up the output section.  The Microsoft specs say sections names in
    657      1.1  christos      image files never contain a '\$'.  Fortunately, lang_..._lookup creates
    658  1.1.1.6  christos      the section if it doesn't exist.  */
    659      1.1  christos   output_secname = xstrdup (secname);
    660      1.1  christos   ps = strchr (output_secname + 1, '\$');
    661  1.1.1.6  christos   *ps = 0;
    662      1.1  christos   os = lang_output_section_statement_lookup (output_secname, constraint, true);
    663      1.1  christos 
    664      1.1  christos   /* Find the '\$' wild statement for this section.  We currently require the
    665      1.1  christos      linker script to explicitly mention "*(.foo\$)".  */
    666      1.1  christos 
    667      1.1  christos   ps[0] = '\$';
    668      1.1  christos   ps[1] = 0;
    669      1.1  christos   for (l = os->children.head; l; l = l->header.next)
    670      1.1  christos     if (l->header.type == lang_wild_statement_enum)
    671      1.1  christos       {
    672      1.1  christos 	struct wildcard_list *sec;
    673      1.1  christos 
    674      1.1  christos 	for (sec = l->wild_statement.section_list; sec; sec = sec->next)
    675      1.1  christos 	  if (sec->spec.name && strcmp (sec->spec.name, output_secname) == 0)
    676      1.1  christos 	    break;
    677      1.1  christos 	if (sec)
    678  1.1.1.8  christos 	  break;
    679      1.1  christos       }
    680      1.1  christos   ps[0] = 0;
    681      1.1  christos   if (l == NULL)
    682      1.1  christos     fatal (_("%P: *(%s\$) missing from linker script\n"), output_secname);
    683      1.1  christos 
    684  1.1.1.6  christos   /* Link the input section in and we're done for now.
    685      1.1  christos      The sections still have to be sorted, but that has to wait until
    686      1.1  christos      all such sections have been processed by us.  The sorting is done by
    687      1.1  christos      sort_sections.  */
    688      1.1  christos   lang_add_section (&l->wild_statement.children, s, NULL, NULL, os);
    689      1.1  christos 
    690  1.1.1.6  christos   return os;
    691      1.1  christos }
    692  1.1.1.6  christos 
    694  1.1.1.6  christos static char *
    695      1.1  christos gld${EMULATION_NAME}_get_script (int *isfile)
    696  1.1.1.6  christos EOF
    697      1.1  christos 
    698  1.1.1.7  christos if test x"$COMPILE_IN" = xyes
    699      1.1  christos then
    700      1.1  christos # Scripts compiled in.
    701      1.1  christos 
    702      1.1  christos # sed commands to quote an ld script as a C string.
    703      1.1  christos sc="-f ${srcdir}/emultempl/stringify.sed"
    704  1.1.1.2  christos 
    705      1.1  christos fragment <<EOF
    706      1.1  christos {
    707      1.1  christos   *isfile = 0;
    708  1.1.1.2  christos 
    709      1.1  christos   if (bfd_link_relocatable (&link_info) && config.build_constructors)
    710      1.1  christos     return
    711      1.1  christos EOF
    712      1.1  christos sed $sc ldscripts/${EMULATION_NAME}.xu                 >> e${EMULATION_NAME}.c
    713      1.1  christos echo '  ; else if (bfd_link_relocatable (&link_info)) return' >> e${EMULATION_NAME}.c
    714      1.1  christos sed $sc ldscripts/${EMULATION_NAME}.xr                 >> e${EMULATION_NAME}.c
    715      1.1  christos echo '  ; else if (!config.text_read_only) return'     >> e${EMULATION_NAME}.c
    716      1.1  christos sed $sc ldscripts/${EMULATION_NAME}.xbn                >> e${EMULATION_NAME}.c
    717      1.1  christos echo '  ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
    718  1.1.1.6  christos sed $sc ldscripts/${EMULATION_NAME}.xn                 >> e${EMULATION_NAME}.c
    719  1.1.1.6  christos echo '  ; else return'                                 >> e${EMULATION_NAME}.c
    720      1.1  christos sed $sc ldscripts/${EMULATION_NAME}.x                  >> e${EMULATION_NAME}.c
    721  1.1.1.6  christos echo '; }'                                             >> e${EMULATION_NAME}.c
    722      1.1  christos 
    723  1.1.1.6  christos else
    724  1.1.1.6  christos # Scripts read from the filesystem.
    725  1.1.1.6  christos 
    726  1.1.1.6  christos fragment <<EOF
    727  1.1.1.6  christos {
    728  1.1.1.6  christos   *isfile = 1;
    729  1.1.1.6  christos 
    730  1.1.1.6  christos   if (bfd_link_relocatable (&link_info) && config.build_constructors)
    731  1.1.1.6  christos     return "ldscripts/${EMULATION_NAME}.xu";
    732  1.1.1.6  christos   else if (bfd_link_relocatable (&link_info))
    733  1.1.1.6  christos     return "ldscripts/${EMULATION_NAME}.xr";
    734  1.1.1.6  christos   else if (!config.text_read_only)
    735  1.1.1.6  christos     return "ldscripts/${EMULATION_NAME}.xbn";
    736      1.1  christos   else if (!config.magic_demand_paged)
    737  1.1.1.6  christos     return "ldscripts/${EMULATION_NAME}.xn";
    738  1.1.1.6  christos   else
    739  1.1.1.6  christos     return "ldscripts/${EMULATION_NAME}.x";
    740  1.1.1.6  christos }
    741  1.1.1.6  christos EOF
    742  1.1.1.6  christos fi
    743  1.1.1.6  christos 
    744  1.1.1.6  christos LDEMUL_AFTER_OPEN=gld${EMULATION_NAME}_after_open
    745  1.1.1.6  christos LDEMUL_BEFORE_ALLOCATION=gld${EMULATION_NAME}_before_allocation
    746  1.1.1.6  christos LDEMUL_PLACE_ORPHAN=gld${EMULATION_NAME}_place_orphan
    747                    LDEMUL_SET_SYMBOLS=gld${EMULATION_NAME}_set_symbols
    748                    LDEMUL_ADD_OPTIONS=gld${EMULATION_NAME}_add_options
    749                    LDEMUL_HANDLE_OPTION=gld${EMULATION_NAME}_handle_option
    750                    
    751                    source_em ${srcdir}/emultempl/emulation.em
    752