summaryrefslogtreecommitdiff
path: root/ld/emultempl/vms.em
blob: 30c1a1602c7e1e5671079eec0068ac4af8109775 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# This shell script emits a C file. -*- C -*-
#   Copyright 2010, 2012
#   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 generic.em.

fragment <<EOF
#include "getopt.h"

static void
gld${EMULATION_NAME}_before_parse (void)
{
  ldfile_set_output_arch ("${ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
  input_flags.dynamic = TRUE;
  config.has_shared = FALSE; /* Not yet.  */

  /* For ia64, harmless for alpha.  */
  link_info.emit_hash = FALSE;
  link_info.spare_dynamic_tags = 0;
}

/* This is called before the input files are opened.  We add the
   standard library.  */

static void
gld${EMULATION_NAME}_create_output_section_statements (void)
{
  lang_add_input_file ("imagelib", lang_input_file_is_l_enum, NULL);
  lang_add_input_file ("starlet", lang_input_file_is_l_enum, NULL);
  lang_add_input_file ("sys\$public_vectors", lang_input_file_is_l_enum, NULL);
}

/* Try to open a dynamic archive.  This is where we know that VMS
   shared images (dynamic libraries) have an extension of .exe.  */

static bfd_boolean
gld${EMULATION_NAME}_open_dynamic_archive (const char *arch ATTRIBUTE_UNUSED,
                                           search_dirs_type *search,
                                           lang_input_statement_type *entry)
{
  char *string;

  if (! entry->flags.maybe_archive)
    return FALSE;

  string = (char *) xmalloc (strlen (search->name)
			     + strlen (entry->filename)
			     + sizeof "/.exe");

  sprintf (string, "%s/%s.exe", search->name, entry->filename);

  if (! ldfile_try_open_bfd (string, entry))
    {
      free (string);
      return FALSE;
    }

  entry->filename = string;

  return TRUE;
}

static int
gld${EMULATION_NAME}_find_potential_libraries
  (char *name, lang_input_statement_type *entry)
{
  return ldfile_open_file_search (name, entry, "", ".olb");
}

/* Place an orphan section.  We use this to put random OVR sections.
   Much borrowed from elf32.em.  */

static lang_output_section_statement_type *
vms_place_orphan (asection *s,
		  const char *secname ATTRIBUTE_UNUSED,
		  int constraint ATTRIBUTE_UNUSED)
{
  static struct orphan_save hold_data =
    {
      "\$DATA\$",
      SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
      0, 0, 0, 0
    };

  /* We have nothing to say for anything other than a final link or an excluded
     section.  */
  if (link_info.relocatable
      || (s->flags & (SEC_EXCLUDE | SEC_LOAD)) != SEC_LOAD)
    return NULL;

  /* FIXME: we should place sections by VMS program section flags.  */

  /* Only handle data sections.  */
  if ((s->flags & SEC_DATA) == 0)
    return NULL;

  if (hold_data.os == NULL)
    hold_data.os = lang_output_section_find (hold_data.name);

  if (hold_data.os != NULL)
    {
      lang_add_section (&hold_data.os->children, s, NULL, hold_data.os);
      return hold_data.os;
    }
  else
    return NULL;
}

/* VMS specific options.  */
#define OPTION_IDENTIFICATION		(300  + 1)

static void
gld${EMULATION_NAME}_add_options
  (int ns ATTRIBUTE_UNUSED,
   char **shortopts ATTRIBUTE_UNUSED,
   int nl,
   struct option **longopts,
   int nrl ATTRIBUTE_UNUSED,
   struct option **really_longopts ATTRIBUTE_UNUSED)
{
  static const struct option xtra_long[] =
  {
    {"identification", required_argument, NULL, OPTION_IDENTIFICATION},
    {NULL, no_argument, NULL, 0}
  };

  *longopts
    = xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
}

static void
gld${EMULATION_NAME}_list_options (FILE *file)
{
  fprintf (file, _("  --identification <string>          Set the identification of the output\n"));
}

static bfd_boolean
gld${EMULATION_NAME}_handle_option (int optc)
{
  switch (optc)
    {
    default:
      return FALSE;

    case OPTION_IDENTIFICATION:
      /* Currently ignored.  */
      break;
    }

  return TRUE;
}

EOF

if test "$OUTPUT_FORMAT" = "elf64-ia64-vms"; then

fragment <<EOF
#include "elf-bfd.h"
EOF

source_em ${srcdir}/emultempl/elf-generic.em

fragment <<EOF

/* This is called after the sections have been attached to output
   sections, but before any sizes or addresses have been set.  */

static void
gld${EMULATION_NAME}_before_allocation (void)
{
  const struct elf_backend_data *bed;

  if (!is_elf_hash_table (link_info.hash))
    return;

  bed = get_elf_backend_data (link_info.output_bfd);

  /* The backend must work out the sizes of all the other dynamic
     sections.  */
  if (elf_hash_table (&link_info)->dynamic_sections_created
      && bed->elf_backend_size_dynamic_sections
      && ! (*bed->elf_backend_size_dynamic_sections) (link_info.output_bfd,
                                                      &link_info))
    einfo ("%P%F: failed to set dynamic section sizes: %E\n");

  before_allocation_default ();
}

static void
gld${EMULATION_NAME}_after_allocation (void)
{
  bfd_boolean need_layout = bfd_elf_discard_info (link_info.output_bfd,
						  &link_info);
  gld${EMULATION_NAME}_map_segments (need_layout);
}

static void
gld${EMULATION_NAME}_after_parse (void)
{
  link_info.relax_pass = 2;
  after_parse_default ();
}
EOF

LDEMUL_BEFORE_ALLOCATION=gld"$EMULATION_NAME"_before_allocation
LDEMUL_AFTER_ALLOCATION=gld"$EMULATION_NAME"_after_allocation

LDEMUL_AFTER_PARSE=gld${EMULATION_NAME}_after_parse
source_em ${srcdir}/emultempl/needrelax.em
fi

LDEMUL_PLACE_ORPHAN=vms_place_orphan
LDEMUL_BEFORE_PARSE=gld"$EMULATION_NAME"_before_parse
LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=gld"$EMULATION_NAME"_create_output_section_statements
LDEMUL_FIND_POTENTIAL_LIBRARIES=gld"$EMULATION_NAME"_find_potential_libraries
LDEMUL_OPEN_DYNAMIC_ARCHIVE=gld"$EMULATION_NAME"_open_dynamic_archive
LDEMUL_ADD_OPTIONS=gld"$EMULATION_NAME"_add_options
LDEMUL_HANDLE_OPTION=gld"$EMULATION_NAME"_handle_option
LDEMUL_LIST_OPTIONS=gld"$EMULATION_NAME"_list_options