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