0bd2318449e577256e44b7e9946f799b3e18f803
[external/binutils.git] / ld / emultempl / hppaosf.em
1 # This shell script emits a C file. -*- C -*-
2 # It does some substitutions.
3 cat >em_${EMULATION_NAME}.c <<EOF
4 /* An emulation for HP PA-RISC OSF/1 linkers.
5    Copyright (C) 1991 Free Software Foundation, Inc.
6    Written by Steve Chamberlain steve@cygnus.com
7
8 This file is part of GLD, the Gnu Linker.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
23
24 #include "bfd.h"
25 #include "sysdep.h"
26
27
28 #include "ld.h"
29 #include "config.h"
30 #include "ldemul.h"
31 #include "ldfile.h"
32 #include "ldexp.h"
33 #include "ldlang.h"
34 #include "ldmisc.h"
35
36 extern  boolean lang_float_flag;
37
38
39 extern enum bfd_architecture ldfile_output_architecture;
40 extern unsigned long ldfile_output_machine;
41 extern char *ldfile_output_machine_name;
42
43 extern bfd *output_bfd;
44
45 static void hppaosf_before_parse()
46 {
47   extern char *lprefix;
48   extern unsigned int lprefix_len;
49   lprefix = "L$";
50   lprefix_len = 2;
51
52   ldfile_output_architecture = bfd_arch_hppa;
53 }
54
55 static lang_input_statement_type *stub_file = 0;
56
57 static lang_input_section_type *stub_input_section = NULL;
58
59 extern lang_statement_list_type *stat_ptr;
60 /* List of statements needed to handle constructors */
61 extern lang_statement_list_type constructor_list;
62
63 static void
64 hppaosf_search_for_padding_statements(s,prev)
65         lang_statement_union_type *s;
66         lang_statement_union_type **prev;
67 {
68   lang_statement_union_type *sprev = NULL;
69   for (; s != (lang_statement_union_type *) NULL; s = s->next)
70     {
71       switch (s->header.type)
72         {
73         case lang_constructors_statement_enum:
74           hppaosf_search_for_padding_statements (constructor_list.head,&constructor_list.head);
75           break;
76         case lang_output_section_statement_enum:
77           hppaosf_search_for_padding_statements
78             (s->output_section_statement.children.head,&s->output_section_statement.children.head);
79           break;
80         case lang_wild_statement_enum:
81           hppaosf_search_for_padding_statements
82             (s->wild_statement.children.head,&s->wild_statement.children.head);
83           break;
84         case lang_data_statement_enum:
85         case lang_object_symbols_statement_enum:
86         case lang_output_statement_enum:
87         case lang_target_statement_enum:
88         case lang_input_section_enum:
89         case lang_input_statement_enum:
90         case lang_assignment_statement_enum:
91         case lang_address_statement_enum:
92           break;
93         case lang_padding_statement_enum:
94           if ( sprev )
95             {
96               sprev->header.next = s->header.next;
97             }
98           else
99             {
100               **prev = *s;
101             }
102           break;
103         default:
104           FAIL ();
105           break;
106         }
107       sprev = s;
108     }
109 }
110
111 static void
112 hppaosf_finish()
113 {
114   extern asymbol *hppa_look_for_stubs_in_section();
115   extern ld_config_type config;
116
117   if (config.relocateable_output == false)
118     {
119       /* check for needed stubs */
120       LANG_FOR_EACH_INPUT_SECTION
121         (statement, abfd, section,
122          (
123           {
124             int new_sym_cnt = 0;
125             int i,j;
126             asymbol *syms = hppa_look_for_stubs_in_section (stub_file->the_bfd,
127                                                             abfd,
128                                                             output_bfd,
129                                                             section,
130                                                             statement->asymbols,
131                                                             &new_sym_cnt);
132
133             if ( (new_sym_cnt > 0) && syms )
134               {
135                 struct symbol_cache_entry **old_asymbols = stub_file->asymbols;
136
137                 stub_file->asymbols = ldmalloc((stub_file->symbol_count + new_sym_cnt) * sizeof(asymbol *));
138
139                 for ( j = 0; j < stub_file->symbol_count; j++ )
140                   stub_file->asymbols[j] = old_asymbols[j];
141                 
142                 for ( j = 0, i = stub_file->symbol_count; j < new_sym_cnt; j++, i++ )
143                   stub_file->asymbols[i] = &syms[j];
144                 
145                 stub_file->symbol_count += new_sym_cnt;
146                 /* Now, attach the contents of the new linker stub(s) */
147                 /* to the linker stub input section. */
148
149                 
150               }
151           }
152           )
153          )
154       /* Add a statement to get the linker stubs included in the output */
155       lang_add_wild(".hppa_linker_stubs",NULL);
156
157       /* If we've added stubs,remove the padding_statements because */
158       /* they are no longer valid */
159       hppaosf_search_for_padding_statements(stat_ptr->head,&(stat_ptr->head));
160     }
161 }
162
163 static void
164 hppaosf_create_output_section_statements()
165 {
166   asection *stub_sec;
167   asection *output_text_sec = bfd_make_section_old_way(output_bfd,".text");
168   lang_input_section_type *new_input_sec;
169   
170   stub_file = lang_add_input_file ("linker stubs",
171                                    lang_input_file_is_fake_enum,
172                                    (char *) NULL);
173   stub_file->the_bfd = bfd_create ("linker stubs", output_bfd);
174   stub_file->symbol_count = 0;
175   stub_file->the_bfd->sections = 0;
176   
177   stub_sec = bfd_make_section_old_way(stub_file->the_bfd,".hppa_linker_stubs");
178   stub_sec->output_section = output_text_sec;
179   bfd_set_section_flags(stub_file->the_bfd, stub_sec, SEC_HAS_CONTENTS | SEC_ALLOC | SEC_CODE | SEC_RELOC );
180   
181   /* The user data of a bfd points to the input statement attached */
182   stub_file->the_bfd->usrdata  = (void *)stub_file;
183   stub_file->common_section =
184     bfd_make_section(stub_file->the_bfd,"COMMON");
185
186   new_input_sec = (lang_input_section_type *)stat_alloc(sizeof(lang_input_section_type));
187   if ( new_input_sec )
188     {
189         lang_output_section_statement_type *text_output_sec;
190         lang_statement_union_type *stmt;
191         lang_wild_statement_type *stub_statement;
192         new_input_sec->section = stub_sec;
193         new_input_sec->ifile = stub_file;
194         new_input_sec->header.type = lang_input_section_enum;
195         new_input_sec->header.next = NULL;
196
197         stub_input_section = new_input_sec;
198
199         /* Find the output_section_statement for .text, */
200         /* then find the wild_statement for .hppa_linker_stubs */
201
202         text_output_sec = lang_output_section_find(".text");
203
204         stmt = text_output_sec->children.head;
205
206         while (stmt && stmt->header.type != lang_wild_statement_enum)
207           {
208                 stmt = stmt->header.next;
209           }
210         
211         if ( stmt )
212           {
213                 lang_wild_statement_type *wstmt = (lang_wild_statement_type *)stmt;
214                 lang_list_init(&wstmt->children);           
215                 lang_statement_append(&wstmt->children,
216                                       (lang_statement_union_type *)new_input_sec,
217                                       &new_input_sec->header.next);
218           }
219     }
220 }
221
222 static void
223 hppaosf_set_output_arch()
224 {
225   /* Set the output architecture and machine if possible */
226   unsigned long  machine = 0;
227   bfd_set_arch_mach(output_bfd, ldfile_output_architecture, machine);
228 }
229
230 static char *
231 hppaosf_get_script(isfile)
232      int *isfile;
233 EOF
234
235 if test -n "$COMPILE_IN"
236 then
237 # Scripts compiled in.
238
239 # sed commands to quote an ld script as a C string.
240 sc='s/["\\]/\\&/g
241 s/$/\\n\\/
242 1s/^/"{/
243 $s/$/n}"/
244 '
245
246 cat >>em_${EMULATION_NAME}.c <<EOF
247 {                            
248   extern ld_config_type config;
249
250   *isfile = 0;
251
252   if (config.relocateable_output == true && config.build_constructors == true)
253     return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
254   else if (config.relocateable_output == true)
255     return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
256   else if (!config.text_read_only)
257     return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
258   else if (!config.magic_demand_paged)
259     return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
260   else
261     return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
262 }
263 EOF
264
265 else
266 # Scripts read from the filesystem.
267
268 cat >>em_${EMULATION_NAME}.c <<EOF
269 {                            
270   extern ld_config_type config;
271
272   *isfile = 1;
273
274   if (config.relocateable_output == true && config.build_constructors == true)
275     return "ldscripts/${EMULATION_NAME}.xu";
276   else if (config.relocateable_output == true)
277     return "ldscripts/${EMULATION_NAME}.xr";
278   else if (!config.text_read_only)
279     return "ldscripts/${EMULATION_NAME}.xbn";
280   else if (!config.magic_demand_paged)
281     return "ldscripts/${EMULATION_NAME}.xn";
282   else
283     return "ldscripts/${EMULATION_NAME}.x";
284 }
285 EOF
286
287 fi
288
289 cat >>em_${EMULATION_NAME}.c <<EOF
290
291 struct ld_emulation_xfer_struct ld_hppaosf_emulation = 
292 {
293   hppaosf_before_parse,
294   syslib_default,
295   hll_default,
296   after_parse_default,
297   after_allocation_default,
298   hppaosf_set_output_arch,
299   ldemul_default_target,
300   before_allocation_default,
301   hppaosf_get_script,
302   "hppaosf",
303   "elf32-hppa",
304   hppaosf_finish,
305   hppaosf_create_output_section_statements
306 };
307 EOF