Thu Aug 31 16:37:07 1995 steve chamberlain <sac@slash.cygnus.com>
[deliverable/binutils-gdb.git] / ld / emultempl / pe.em
CommitLineData
5f8ac7e7
SC
1# This shell script emits a C file. -*- C -*-
2# It does some substitutions.
3cat >e${EMULATION_NAME}.c <<EOF
4/* For WINDOWS_NT */
5/* The original file generated returned different default scripts depending
6 on whether certain switches were set, but these switches pertain to the
7 Linux system and that particular version of coff. In the NT case, we
8 only determine if the subsystem is console or windows in order to select
9 the correct entry point by default. */
10
11
12/* This file is part of GLD, the Gnu Linker.
13
14This program is free software; you can redistribute it and/or modify
15it under the terms of the GNU General Public License as published by
16the Free Software Foundation; either version 2 of the License, or
17(at your option) any later version.
18
19This program is distributed in the hope that it will be useful,
20but WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22GNU General Public License for more details.
23
24You should have received a copy of the GNU General Public License
25along with this program; if not, write to the Free Software
26Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27
28
29#include "bfd.h"
30#include "sysdep.h"
31#include "bfdlink.h"
32#include "getopt.h"
33#include "ld.h"
34#include "config.h"
35#include "ld.h"
36#include "ldmain.h"
37#include "ldgram.h"
38#include "ldexp.h"
39#include "ldlang.h"
40#include "ldemul.h"
41#include "ldlex.h"
42#include "ldmisc.h"
43#include "ldctor.h"
44#include "ldfile.h"
45#include "coff/internal.h"
46#include "../bfd/libcoff.h"
47
48static void gld_${EMULATION_NAME}_before_parse PARAMS ((void));
49static char *gld_${EMULATION_NAME}_get_script PARAMS ((int *isfile));
50
51
52static struct internal_extra_pe_aouthdr pe;
53static int dll;
54
55static void
56gld_${EMULATION_NAME}_before_parse()
57{
58 ldfile_output_architecture = bfd_arch_${ARCH};
59}
60
61
62/* Used for setting flags in the PE header. */
63#define OPTION_BASE_FILE (300 + 1)
64#define OPTION_DLL (OPTION_BASE_FILE + 1)
65#define OPTION_FILE_ALIGNMENT (OPTION_DLL + 1)
66#define OPTION_IMAGE_BASE (OPTION_FILE_ALIGNMENT + 1)
67#define OPTION_MAJOR_IMAGE_VERSION (OPTION_IMAGE_BASE + 1)
68#define OPTION_MAJOR_OS_VERSION (OPTION_MAJOR_IMAGE_VERSION + 1)
69#define OPTION_MAJOR_SUBSYSTEM_VERSION (OPTION_MAJOR_OS_VERSION + 1)
70#define OPTION_MINOR_IMAGE_VERSION (OPTION_MAJOR_SUBSYSTEM_VERSION + 1)
71#define OPTION_MINOR_OS_VERSION (OPTION_MINOR_IMAGE_VERSION + 1)
72#define OPTION_MINOR_SUBSYSTEM_VERSION (OPTION_MINOR_OS_VERSION + 1)
73#define OPTION_SECTION_ALIGNMENT (OPTION_MINOR_SUBSYSTEM_VERSION + 1)
74#define OPTION_STACK (OPTION_SECTION_ALIGNMENT + 1)
75#define OPTION_SUBSYSTEM (OPTION_STACK + 1)
76#define OPTION_HEAP (OPTION_SUBSYSTEM + 1)
77
78 static struct option longopts[] = {
79 /* PE options */
80 {"base-file", required_argument, NULL, OPTION_BASE_FILE},
81 {"dll", no_argument, NULL, OPTION_DLL},
82 {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
83 {"heap", required_argument, NULL, OPTION_HEAP},
84 {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
85 {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
86 {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
87 {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
88 {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
89 {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
90 {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
91 {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
92 {"stack", required_argument, NULL, OPTION_STACK},
93 {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
94 {NULL, no_argument, NULL, 0}
95 };
96
97
98/* PE/WIN32; added routines to get the subsystem type, heap and/or stack
99 parameters which may be input from the command line */
100
101
102
103typedef struct {
104 void *ptr;
105 int size;
106 int value;
107 char *symbol;
108 int inited;
109} definfo;
110
111#define D(field,symbol,def) {&pe.field,sizeof(pe.field), def, symbol,0}
112
113static definfo init[] =
114{
115 /* imagebase must be first */
116#define IMAGEBASEOFF 0
117 D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE),
118#define DLLOFF 1
119 {&dll, sizeof(dll), 0, "__dll__"},
120 D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
121 D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
122 D(MajorOperatingSystemVersion,"__major_os_version__", 4),
123 D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
124 D(MajorImageVersion,"__major_image_version__", 1),
125 D(MinorImageVersion,"__minor_image_version__", 0),
126 D(MajorSubsystemVersion,"__major_subsystem_version__", 4),
127 D(MinorSubsystemVersion,"__minor_subsystem_version__", 0),
128 D(Subsystem,"__subsystem__", 3),
129 D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x100000),
130 D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
131 D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
132 D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
133 D(LoaderFlags,"__loader_flags__", 0x0),
134 0
135};
136
137
138static void
139set_pe_name (name, val)
140 char *name;
141 long val;
142{
143 int i;
144 /* Find the name and set it. */
145 for (i = 0; init[i].ptr; i++)
146 {
147 if (strcmp (name, init[i].symbol) == 0)
148 {
149 init[i].value = val;
150 init[i].inited = 1;
151 return;
152 }
153 }
154 abort();
155}
156
157
158static void
159set_pe_subsystem ()
160{
161 int i;
162 static struct
163 {
164 char *name ;
165 int value;
166 }
167 v[] =
168 {
169 {"native", BFD_PE_NATIVE},
170 {"windows",BFD_PE_WINDOWS},
171 {"console",BFD_PE_CONSOLE},
172 {"os2",BFD_PE_OS2},
173 {"posix", BFD_PE_POSIX},
174 {0,0}
175 };
176
177 for (i = 0; v[i].name; i++)
178 {
179 if (!strcmp (optarg, v[i].name))
180 {
181 set_pe_name ("__subsystem__", v[i].value);
182 return;
183 }
184 }
185 einfo ("%P%F: invalid subsystem type %s\n", optarg);
186}
187
188
189
190static void
191set_pe_value (name)
192 char *name;
193
194{
195 char *end;
196 set_pe_name (name, strtoul (optarg, &end, 16));
197 if (end == optarg)
198 {
199 einfo ("%P%F: invalid hex number for PE parameter '%s'\n", optarg);
200 }
201
202 optarg = end;
203}
204
205static void
206set_pe_stack_heap (resname, comname)
207 char *resname;
208 char *comname;
209{
210 char *begin_commit;
211 char *end;
212
213 set_pe_value (resname);
214 if (*optarg == ',')
215 {
216 optarg++;
217 set_pe_value (comname);
218 }
219 else if (*optarg)
220 {
221 einfo ("%P%F: strange hex info for PE parameter '%s'\n", optarg);
222 }
223}
224
225
226
227static int
228gld_${EMULATION_NAME}_parse_args(argc, argv)
229 int argc;
230 char **argv;
231{
232 int longind;
233 int optc;
234 int prevoptind = optind;
235 int prevopterr = opterr;
236 opterr = 0;
237 optc = getopt_long_only (argc, argv, "-", longopts, &longind);
238 opterr = prevopterr;
239 switch (optc)
240 {
241 default:
242 optind = prevoptind;
243 return 0;
244
245 case OPTION_BASE_FILE:
246 link_info.base_file = (PTR) fopen (optarg,"w");
247 if (link_info.base_file == NULL)
248 {
249 fprintf (stderr, "%s: Can't open base file %s\n",
250 program_name, optarg);
251 xexit (1);
252 }
253 break;
254
255 /* PE options */
256 case OPTION_HEAP:
257 set_pe_stack_heap ("__heap_reserve__", "__heap_commit__");
258 break;
259 case OPTION_STACK:
260 set_pe_stack_heap ("__stack_reserve__", "__stack_commit__");
261 break;
262 case OPTION_SUBSYSTEM:
263 set_pe_subsystem ();
264 break;
265 case OPTION_MAJOR_OS_VERSION:
266 set_pe_value ("__major_os_version__");
267 break;
268 case OPTION_MINOR_OS_VERSION:
269 set_pe_value ("__minor_os_version__");
270 break;
271 case OPTION_MAJOR_SUBSYSTEM_VERSION:
272 set_pe_value ("__major_subsystem_version__");
273 break;
274 case OPTION_MINOR_SUBSYSTEM_VERSION:
275 set_pe_value ("__minor_subsytem_version__");
276 break;
277 case OPTION_MAJOR_IMAGE_VERSION:
278 set_pe_value ("__major_image_version__");
279 break;
280 case OPTION_MINOR_IMAGE_VERSION:
281 set_pe_value ("__minor_image_version__");
282 break;
283 case OPTION_FILE_ALIGNMENT:
284 set_pe_value ("__file_alignment__");
285 break;
286 case OPTION_SECTION_ALIGNMENT:
287 set_pe_value ("__section_alignment__");
288 break;
289 case OPTION_DLL:
290 set_pe_name ("__dll__", 1);
291 break;
292 case OPTION_IMAGE_BASE:
293 set_pe_value ("__image_base__");
294 break;
295 }
296 return 1;
297}
298
299static void
300gld_${EMULATION_NAME}_set_symbols()
301{
302
303 /* Run through and invent symbols for all the
304 names and insert the defaults. */
305 int j;
306
307 if (!init[IMAGEBASEOFF].inited)
308 init[IMAGEBASEOFF].value = init[DLLOFF].value
309 ? NT_DLL_IMAGE_BASE : NT_EXE_IMAGE_BASE;
310
311 for (j = 0; init[j].ptr; j++)
312 {
313 long val = init[j].value;
314 lang_add_assignment (exp_assop ('=' ,init[j].symbol, exp_intop (val)));
315 if (init[j].size == sizeof(short))
316 *(short *)init[j].ptr = val;
317 else if (init[j].size == sizeof(int))
318 *(int *)init[j].ptr = val;
319 else if (init[j].size == sizeof(long))
320 *(long *)init[j].ptr = val;
321 else abort();
322 }
323
324 if (pe.FileAlignment >
325 pe.SectionAlignment)
326 {
327 einfo ("%P: warning, file alignment > section alignment.\n");
328 }
329}
330
331static void
332gld_${EMULATION_NAME}_after_open()
333{
334 /* Pass the wacky PE command line options into the output bfd */
335 struct internal_extra_pe_aouthdr *i;
336 if (!coff_data(output_bfd)->pe)
337 {
338 einfo ("%F%P: PE operations on non PE file.\n");
339 }
340
341 pe_data(output_bfd)->pe_opthdr = pe;
342 pe_data(output_bfd)->dll = init[DLLOFF].value;
343
344}
345
346/* Callback function for qsort in sort_sections. */
347
348static int sfunc (a, b)
349void *a;
350void *b;
351{
352 lang_statement_union_type **ra = a;
353 lang_statement_union_type **rb = b;
354 return strcmp ((*ra)->input_section.ifile->filename,
355 (*rb)->input_section.ifile->filename);
356}
357
358/* Sort the input sections of archives into filename order. */
359\f
360static void
361sort_sections (s)
362 lang_statement_union_type *s;
363{
364 for (; s ; s = s->next)
365 switch (s->header.type)
366 {
367 case lang_output_section_statement_enum:
368 sort_sections (s->output_section_statement.children.head);
369 break;
370 case lang_wild_statement_enum:
371 {
372 lang_statement_union_type **p = &s->wild_statement.children.head;
373
374 /* Sort any children in the same archive. Run through all
375 the children of this wild statement, when an
376 input_section in an archive is found, scan forward to
377 find all input_sections which are in the same archive.
378 Sort them by their filename and then re-thread the
379 pointer chain. */
380
381 while (*p)
382 {
383 lang_statement_union_type *start = *p;
384 if (start->header.type != lang_input_section_enum
385 || !start->input_section.ifile->the_bfd->my_archive)
386 p = &(start->header.next);
387 else
388 {
389 lang_statement_union_type **vec;
390 lang_statement_union_type *end;
391 lang_statement_union_type *np;
392 int count;
393 int i;
394
395 for (end = start, count = 0;
396 end && end->header.type == lang_input_section_enum
397 && (end->input_section.ifile->the_bfd->my_archive
398 == start->input_section.ifile->the_bfd->my_archive);
399 end = end->next)
400 count++;
401
402 np = end;
403
404 vec = (lang_statement_union_type **)
405 alloca (count * sizeof (lang_statement_union_type *));
406
407 for (end = start, i = 0; i < count; i++, end = end->next)
408 vec[i] = end;
409
410 qsort (vec, count, sizeof (vec[0]), sfunc);
411
412 /* Fill in the next pointers again. */
413 *p = vec[0];
414 for (i = 0; i < count - 1; i++)
415 vec[i]->header.next = vec[i + 1];
416 vec[i]->header.next = np;
417 p = &(vec[i]->header.next);
418 }
419 }
420 }
421 break;
422 default:
423 break;
424 }
425}
426
427static void
428gld_${EMULATION_NAME}_before_allocation()
429{
430 extern lang_statement_list_type *stat_ptr;
431 sort_sections (*stat_ptr);
432}
433
434static char *
435gld_${EMULATION_NAME}_get_script(isfile)
436 int *isfile;
437EOF
438# Scripts compiled in.
439# sed commands to quote an ld script as a C string.
440sc="-f ${srcdir}/emultempl/stringify.sed"
441
442cat >>e${EMULATION_NAME}.c <<EOF
443{
444 *isfile = 0;
445
446 if (link_info.relocateable == true && config.build_constructors == true)
447 return
448EOF
449sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
450echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
451sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c
452echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c
453sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c
454echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
455sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
456echo ' ; else return' >> e${EMULATION_NAME}.c
457sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
458echo '; }' >> e${EMULATION_NAME}.c
459
460cat >>e${EMULATION_NAME}.c <<EOF
461
462
463
464struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
465{
466 gld_${EMULATION_NAME}_before_parse,
467 syslib_default,
468 hll_default,
469 after_parse_default,
470 gld_${EMULATION_NAME}_after_open,
471 after_allocation_default,
472 set_output_arch_default,
473 ldemul_default_target,
474 gld_${EMULATION_NAME}_before_allocation,
475 gld_${EMULATION_NAME}_get_script,
476 "${EMULATION_NAME}",
477 "${OUTPUT_FORMAT}",
478 NULL, /* finish */
479 NULL, /* create output section statements */
480 NULL, /* open dynamic archive */
481 NULL, /* place orphan */
482 gld_${EMULATION_NAME}_set_symbols,
483 gld_${EMULATION_NAME}_parse_args
484};
485EOF
486
This page took 0.043785 seconds and 4 git commands to generate.