Implement ELF linker -z global option
[platform/upstream/binutils.git] / ld / emultempl / lnk960.em
1 # This shell script emits a C file. -*- C -*-
2 # It does some substitutions.
3 fragment <<EOF
4 /* intel coff loader emulation specific stuff
5    Copyright 1991, 1992, 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2003,
6    2005, 2007, 2008 Free Software Foundation, Inc.
7    Written by Steve Chamberlain steve@cygnus.com
8
9    This file is part of the GNU Binutils.
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
24    MA 02110-1301, USA.  */
25
26 #include "sysdep.h"
27 #include "libiberty.h"
28 #include "bfd.h"
29 #include "bfdlink.h"
30
31 /*#include "archures.h"*/
32 #include "ld.h"
33 #include "ldmain.h"
34 #include "ldmisc.h"
35 #include "ldexp.h"
36 #include "ldlang.h"
37 #include "ldfile.h"
38 #include "ldemul.h"
39
40 typedef struct lib_list {
41   char *name;
42   struct lib_list *next;
43 } lib_list_type;
44
45 static lib_list_type *hll_list;
46 static lib_list_type **hll_list_tail = &hll_list;
47
48 static lib_list_type *syslib_list;
49 static lib_list_type **syslib_list_tail = &syslib_list;
50
51
52 static void
53 append (lib_list_type ***list, char *name)
54 {
55   lib_list_type *element = (lib_list_type *) xmalloc (sizeof (lib_list_type));
56
57   element->name = name;
58   element->next = (lib_list_type *) NULL;
59   **list = element;
60   *list = &element->next;
61
62 }
63
64 static bfd_boolean had_hll = FALSE;
65 static bfd_boolean had_hll_name = FALSE;
66
67 static void
68 lnk960_hll (char *name)
69 {
70   had_hll = TRUE;
71   if (name != (char *) NULL)
72     {
73       had_hll_name = TRUE;
74       append (&hll_list_tail, name);
75     }
76 }
77
78 static void
79 lnk960_syslib (char *name)
80 {
81   append (&syslib_list_tail, name);
82 }
83
84
85 static void
86 lnk960_before_parse (void)
87 {
88   char *name = getenv ("I960BASE");
89
90   if (name == (char *) NULL)
91     {
92       name = getenv("G960BASE");
93       if (name == (char *) NULL)
94         einfo ("%P%F I960BASE and G960BASE not set\n");
95     }
96
97   ldfile_add_library_path (concat (name, "/lib", (const char *) NULL), FALSE);
98   ldfile_output_architecture = bfd_arch_i960;
99   ldfile_output_machine = bfd_mach_i960_core;
100 }
101
102 static void
103 add_on (lib_list_type *list, lang_input_file_enum_type search)
104 {
105   while (list)
106     {
107       lang_add_input_file (list->name, search, (char *) NULL);
108       list = list->next;
109     }
110 }
111
112 static void
113 lnk960_after_parse (void)
114 {
115   /* If there has been no arch, default to -KB */
116   if (ldfile_output_machine_name[0] == 0)
117     ldfile_add_arch ("KB");
118
119   /* if there has been no hll list then add our own */
120
121   if (had_hll && !had_hll_name)
122     {
123       append (&hll_list_tail, "cg");
124       if (ldfile_output_machine == bfd_mach_i960_ka_sa
125           || ldfile_output_machine == bfd_mach_i960_ca)
126         append (&hll_list_tail, "fpg");
127     }
128
129   add_on (hll_list, lang_input_file_is_l_enum);
130   add_on (syslib_list, lang_input_file_is_search_file_enum);
131 }
132
133 /* Create a symbol with the given name with the value of the
134    address of first byte of the section named.
135
136    If the symbol already exists, then do nothing.  */
137
138 static void
139 symbol_at_beginning_of (const char *secname, const char *name)
140 {
141   struct bfd_link_hash_entry *h;
142
143   h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE);
144   if (h == NULL)
145     einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
146
147   if (h->type == bfd_link_hash_new
148       || h->type == bfd_link_hash_undefined)
149     {
150       asection *sec;
151
152       h->type = bfd_link_hash_defined;
153
154       sec = bfd_get_section_by_name (link_info.output_bfd, secname);
155       if (sec == NULL)
156         sec = bfd_abs_section_ptr;
157       h->u.def.value = 0;
158       h->u.def.section = sec;
159     }
160 }
161
162 /* Create a symbol with the given name with the value of the
163    address of the first byte after the end of the section named.
164
165    If the symbol already exists, then do nothing.  */
166
167 static void
168 symbol_at_end_of (const char *secname, const char *name)
169 {
170   struct bfd_link_hash_entry *h;
171
172   h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE);
173   if (h == NULL)
174     einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
175
176   if (h->type == bfd_link_hash_new
177       || h->type == bfd_link_hash_undefined)
178     {
179       asection *sec;
180
181       h->type = bfd_link_hash_defined;
182
183       sec = bfd_get_section_by_name (link_info.output_bfd, secname);
184       if (sec == NULL)
185         sec = bfd_abs_section_ptr;
186       h->u.def.value = sec->size;
187       h->u.def.section = sec;
188     }
189 }
190
191 static void
192 lnk960_after_allocation (void)
193 {
194   if (!link_info.relocatable)
195     {
196       symbol_at_end_of (".text", "_etext");
197       symbol_at_end_of (".data", "_edata");
198       symbol_at_beginning_of (".bss", "_bss_start");
199       symbol_at_end_of (".bss", "_end");
200     }
201 }
202
203
204 static struct
205  {
206    unsigned  long number;
207    char *name;
208  }
209 machine_table[] =
210 {
211   { bfd_mach_i960_core  ,"CORE" },
212   { bfd_mach_i960_kb_sb ,"KB" },
213   { bfd_mach_i960_kb_sb ,"SB" },
214   { bfd_mach_i960_mc    ,"MC" },
215   { bfd_mach_i960_xa    ,"XA" },
216   { bfd_mach_i960_ca    ,"CA" },
217   { bfd_mach_i960_ka_sa ,"KA" },
218   { bfd_mach_i960_ka_sa ,"SA" },
219   { bfd_mach_i960_jx    ,"JX" },
220   { bfd_mach_i960_hx    ,"HX" },
221
222   { bfd_mach_i960_core  ,"core" },
223   { bfd_mach_i960_kb_sb ,"kb" },
224   { bfd_mach_i960_kb_sb ,"sb" },
225   { bfd_mach_i960_mc    ,"mc" },
226   { bfd_mach_i960_xa    ,"xa" },
227   { bfd_mach_i960_ca    ,"ca" },
228   { bfd_mach_i960_ka_sa ,"ka" },
229   { bfd_mach_i960_ka_sa ,"sa" },
230   { bfd_mach_i960_jx    ,"jx" },
231   { bfd_mach_i960_hx    ,"hx" },
232
233   { 0, (char *) NULL }
234 };
235
236 static void
237 lnk960_set_output_arch (void)
238 {
239   /* Set the output architecture and machine if possible */
240   unsigned int i;
241   ldfile_output_machine = bfd_mach_i960_core;
242   for (i= 0; machine_table[i].name != (char*) NULL; i++)
243     {
244       if (strcmp (ldfile_output_machine_name, machine_table[i].name) == 0)
245         {
246           ldfile_output_machine = machine_table[i].number;
247           break;
248         }
249     }
250   bfd_set_arch_mach (link_info.output_bfd, ldfile_output_architecture,
251                      ldfile_output_machine);
252 }
253
254 static char *
255 lnk960_choose_target (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
256 {
257   char *from_outside = getenv (TARGET_ENVIRON);
258   if (from_outside != (char *) NULL)
259     return from_outside;
260 #ifdef LNK960_LITTLE
261   return "coff-Intel-little";
262 #else
263   return "coff-Intel-big";
264 #endif
265 }
266
267 static char *
268 lnk960_get_script (int *isfile)
269 EOF
270
271 if test -n "$COMPILE_IN"
272 then
273 # Scripts compiled in.
274
275 # sed commands to quote an ld script as a C string.
276 sc="-f stringify.sed"
277
278 fragment <<EOF
279 {
280   *isfile = 0;
281
282   if (link_info.relocatable && config.build_constructors)
283     return
284 EOF
285 sed $sc ldscripts/${EMULATION_NAME}.xu                 >> e${EMULATION_NAME}.c
286 echo '  ; else if (link_info.relocatable) return'     >> e${EMULATION_NAME}.c
287 sed $sc ldscripts/${EMULATION_NAME}.xr                 >> e${EMULATION_NAME}.c
288 echo '  ; else if (!config.text_read_only) return'     >> e${EMULATION_NAME}.c
289 sed $sc ldscripts/${EMULATION_NAME}.xbn                >> e${EMULATION_NAME}.c
290 echo '  ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
291 sed $sc ldscripts/${EMULATION_NAME}.xn                 >> e${EMULATION_NAME}.c
292 echo '  ; else return'                                 >> e${EMULATION_NAME}.c
293 sed $sc ldscripts/${EMULATION_NAME}.x                  >> e${EMULATION_NAME}.c
294 echo '; }'                                             >> e${EMULATION_NAME}.c
295
296 else
297 # Scripts read from the filesystem.
298
299 fragment <<EOF
300 {
301   *isfile = 1;
302
303   if (link_info.relocatable && config.build_constructors)
304     return "ldscripts/${EMULATION_NAME}.xu";
305   else if (link_info.relocatable)
306     return "ldscripts/${EMULATION_NAME}.xr";
307   else if (!config.text_read_only)
308     return "ldscripts/${EMULATION_NAME}.xbn";
309   else if (!config.magic_demand_paged)
310     return "ldscripts/${EMULATION_NAME}.xn";
311   else
312     return "ldscripts/${EMULATION_NAME}.x";
313 }
314 EOF
315
316 fi
317
318 fragment <<EOF
319
320 struct ld_emulation_xfer_struct ld_lnk960_emulation =
321 {
322   lnk960_before_parse,
323   lnk960_syslib,
324   lnk960_hll,
325   lnk960_after_parse,
326   after_open_default,
327   lnk960_after_allocation,
328   lnk960_set_output_arch,
329   lnk960_choose_target,
330   before_allocation_default,
331   lnk960_get_script,
332   "lnk960",
333   "",
334   finish_default,
335   NULL, /* create output section statements */
336   NULL, /* open dynamic archive */
337   NULL, /* place orphan */
338   NULL, /* set symbols */
339   NULL, /* parse args */
340   NULL, /* add_options */
341   NULL, /* handle_option */
342   NULL, /* unrecognized file */
343   NULL, /* list options */
344   NULL, /* recognized file */
345   NULL, /* find_potential_libraries */
346   NULL  /* new_vers_pattern */
347 };
348 EOF