daily update
[binutils.git] / ld / emultempl / hppaelf.em
blobedd8e0137ccb894bd4cd6a806947fc65bf5423ce
1 # This shell script emits a C file. -*- C -*-
2 #   Copyright 1991, 1993, 1994, 1997, 1999, 2000, 2001, 2002, 2003
3 #   Free Software Foundation, Inc.
5 # This file is part of GLD, the Gnu Linker.
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 # This file is sourced from elf32.em, and defines extra hppa-elf
23 # specific routines.
25 cat >>e${EMULATION_NAME}.c <<EOF
27 #include "ldctor.h"
28 #include "elf32-hppa.h"
31 /* Fake input file for stubs.  */
32 static lang_input_statement_type *stub_file;
34 /* Type of import/export stubs to build.  For a single sub-space model,
35    we can build smaller import stubs and there is no need for export
36    stubs.  */
37 static int multi_subspace = 0;
39 /* Whether we need to call hppa_layout_sections_again.  */
40 static int need_laying_out = 0;
42 /* Maximum size of a group of input sections that can be handled by
43    one stub section.  A value of +/-1 indicates the bfd back-end
44    should use a suitable default size.  */
45 static bfd_signed_vma group_size = 1;
47 /* Stops the linker merging .text sections on a relocatable link,
48    and adds millicode library to the list of input files.  */
50 static void
51 hppaelf_after_parse (void)
53   if (link_info.relocatable)
54     lang_add_unique (".text");
55 #if 0 /* Enable this once we split millicode stuff from libgcc.  */
56   else
57     lang_add_input_file ("milli",
58                          lang_input_file_is_l_enum,
59                          NULL);
60 #endif
63 /* This is called before the input files are opened.  We create a new
64    fake input file to hold the stub sections.  */
66 static void
67 hppaelf_create_output_section_statements (void)
69   extern const bfd_target bfd_elf32_hppa_linux_vec;
70   extern const bfd_target bfd_elf32_hppa_vec;
72   if (link_info.hash->creator != &bfd_elf32_hppa_linux_vec
73       && link_info.hash->creator != &bfd_elf32_hppa_vec)
74     return;
76   stub_file = lang_add_input_file ("linker stubs",
77                                    lang_input_file_is_fake_enum,
78                                    NULL);
79   stub_file->the_bfd = bfd_create ("linker stubs", output_bfd);
80   if (stub_file->the_bfd == NULL
81       || ! bfd_set_arch_mach (stub_file->the_bfd,
82                               bfd_get_arch (output_bfd),
83                               bfd_get_mach (output_bfd)))
84     {
85       einfo ("%X%P: can not create BFD %E\n");
86       return;
87     }
89   ldlang_add_file (stub_file);
93 struct hook_stub_info
95   lang_statement_list_type add;
96   asection *input_section;
99 /* Traverse the linker tree to find the spot where the stub goes.  */
101 static bfd_boolean
102 hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
104   lang_statement_union_type *l;
105   bfd_boolean ret;
107   for (; (l = *lp) != NULL; lp = &l->header.next)
108     {
109       switch (l->header.type)
110         {
111         case lang_constructors_statement_enum:
112           ret = hook_in_stub (info, &constructor_list.head);
113           if (ret)
114             return ret;
115           break;
117         case lang_output_section_statement_enum:
118           ret = hook_in_stub (info,
119                               &l->output_section_statement.children.head);
120           if (ret)
121             return ret;
122           break;
124         case lang_wild_statement_enum:
125           ret = hook_in_stub (info, &l->wild_statement.children.head);
126           if (ret)
127             return ret;
128           break;
130         case lang_group_statement_enum:
131           ret = hook_in_stub (info, &l->group_statement.children.head);
132           if (ret)
133             return ret;
134           break;
136         case lang_input_section_enum:
137           if (l->input_section.section == info->input_section)
138             {
139               /* We've found our section.  Insert the stub immediately
140                  before its associated input section.  */
141               *lp = info->add.head;
142               *(info->add.tail) = l;
143               return TRUE;
144             }
145           break;
147         case lang_data_statement_enum:
148         case lang_reloc_statement_enum:
149         case lang_object_symbols_statement_enum:
150         case lang_output_statement_enum:
151         case lang_target_statement_enum:
152         case lang_input_statement_enum:
153         case lang_assignment_statement_enum:
154         case lang_padding_statement_enum:
155         case lang_address_statement_enum:
156         case lang_fill_statement_enum:
157           break;
159         default:
160           FAIL ();
161           break;
162         }
163     }
164   return FALSE;
168 /* Call-back for elf32_hppa_size_stubs.  */
170 /* Create a new stub section, and arrange for it to be linked
171    immediately before INPUT_SECTION.  */
173 static asection *
174 hppaelf_add_stub_section (const char *stub_sec_name, asection *input_section)
176   asection *stub_sec;
177   flagword flags;
178   asection *output_section;
179   const char *secname;
180   lang_output_section_statement_type *os;
181   struct hook_stub_info info;
183   stub_sec = bfd_make_section_anyway (stub_file->the_bfd, stub_sec_name);
184   if (stub_sec == NULL)
185     goto err_ret;
187   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
188            | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
189   if (!bfd_set_section_flags (stub_file->the_bfd, stub_sec, flags))
190     goto err_ret;
192   output_section = input_section->output_section;
193   secname = bfd_get_section_name (output_section->owner, output_section);
194   os = lang_output_section_find (secname);
196   info.input_section = input_section;
197   lang_list_init (&info.add);
198   lang_add_section (&info.add, stub_sec, os, stub_file);
200   if (info.add.head == NULL)
201     goto err_ret;
203   if (hook_in_stub (&info, &os->children.head))
204     return stub_sec;
206  err_ret:
207   einfo ("%X%P: can not make stub section: %E\n");
208   return NULL;
212 /* Another call-back for elf32_hppa_size_stubs.  */
214 static void
215 hppaelf_layout_sections_again (void)
217   /* If we have changed sizes of the stub sections, then we need
218      to recalculate all the section offsets.  This may mean we need to
219      add even more stubs.  */
220   need_laying_out = 0;
222   lang_reset_memory_regions ();
224   /* Resize the sections.  */
225   lang_size_sections (stat_ptr->head, abs_output_section,
226                       &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
228   /* Redo special stuff.  */
229   ldemul_after_allocation ();
231   /* Do the assignments again.  */
232   lang_do_assignments (stat_ptr->head, abs_output_section,
233                        (fill_type *) 0, (bfd_vma) 0);
237 static void
238 build_section_lists (lang_statement_union_type *statement)
240   if (statement->header.type == lang_input_section_enum
241       && !statement->input_section.ifile->just_syms_flag
242       && (statement->input_section.section->flags & SEC_EXCLUDE) == 0
243       && statement->input_section.section->output_section != NULL
244       && statement->input_section.section->output_section->owner == output_bfd)
245     {
246       elf32_hppa_next_input_section (&link_info,
247                                      statement->input_section.section);
248     }
252 /* Final emulation specific call.  For the PA we use this opportunity
253    to build linker stubs.  */
255 static void
256 gld${EMULATION_NAME}_finish (void)
258   /* bfd_elf_discard_info just plays with debugging sections,
259      ie. doesn't affect any code, so we can delay resizing the
260      sections.  It's likely we'll resize everything in the process of
261      adding stubs.  */
262   if (bfd_elf_discard_info (output_bfd, &link_info))
263     need_laying_out = 1;
265   /* If generating a relocatable output file, then we don't
266      have to examine the relocs.  */
267   if (stub_file != NULL && !link_info.relocatable)
268     {
269       int ret = elf32_hppa_setup_section_lists (output_bfd, &link_info);
271       if (ret != 0)
272         {
273           if (ret < 0)
274             {
275               einfo ("%X%P: can not size stub section: %E\n");
276               return;
277             }
279           lang_for_each_statement (build_section_lists);
281           /* Call into the BFD backend to do the real work.  */
282           if (! elf32_hppa_size_stubs (output_bfd,
283                                        stub_file->the_bfd,
284                                        &link_info,
285                                        multi_subspace,
286                                        group_size,
287                                        &hppaelf_add_stub_section,
288                                        &hppaelf_layout_sections_again))
289             {
290               einfo ("%X%P: can not size stub section: %E\n");
291               return;
292             }
293         }
294     }
296   if (need_laying_out)
297     hppaelf_layout_sections_again ();
299   if (! link_info.relocatable)
300     {
301       /* Set the global data pointer.  */
302       if (! elf32_hppa_set_gp (output_bfd, &link_info))
303         {
304           einfo ("%X%P: can not set gp\n");
305           return;
306         }
308       /* Now build the linker stubs.  */
309       if (stub_file != NULL && stub_file->the_bfd->sections != NULL)
310         {
311           if (! elf32_hppa_build_stubs (&link_info))
312             einfo ("%X%P: can not build stubs: %E\n");
313         }
314     }
318 /* Avoid processing the fake stub_file in vercheck, stat_needed and
319    check_needed routines.  */
321 static void (*real_func) (lang_input_statement_type *);
323 static void hppa_for_each_input_file_wrapper (lang_input_statement_type *l)
325   if (l != stub_file)
326     (*real_func) (l);
329 static void
330 hppa_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
332   real_func = func;
333   lang_for_each_input_file (&hppa_for_each_input_file_wrapper);
336 #define lang_for_each_input_file hppa_lang_for_each_input_file
340 # Define some shell vars to insert bits of code into the standard elf
341 # parse_args and list_options functions.
343 PARSE_AND_LIST_PROLOGUE='
344 #define OPTION_MULTI_SUBSPACE           301
345 #define OPTION_STUBGROUP_SIZE           (OPTION_MULTI_SUBSPACE + 1)
348 PARSE_AND_LIST_LONGOPTS='
349   { "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE },
350   { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
353 PARSE_AND_LIST_OPTIONS='
354   fprintf (file, _("\
355   --multi-subspace      Generate import and export stubs to support\n\
356                           multiple sub-space shared libraries\n"
357                    ));
358   fprintf (file, _("\
359   --stub-group-size=N   Maximum size of a group of input sections that can be\n\
360                           handled by one stub section.  A negative value\n\
361                           locates all stubs before their branches (with a\n\
362                           group size of -N), while a positive value allows\n\
363                           two groups of input sections, one before, and one\n\
364                           after each stub section.  Values of +/-1 indicate\n\
365                           the linker should choose suitable defaults.\n"
366                    ));
369 PARSE_AND_LIST_ARGS_CASES='
370     case OPTION_MULTI_SUBSPACE:
371       multi_subspace = 1;
372       break;
374     case OPTION_STUBGROUP_SIZE:
375       {
376         const char *end;
377         group_size = bfd_scan_vma (optarg, &end, 0);
378         if (*end)
379           einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
380       }
381       break;
384 # Put these extra hppaelf routines in ld_${EMULATION_NAME}_emulation
386 LDEMUL_AFTER_PARSE=hppaelf_after_parse
387 LDEMUL_FINISH=gld${EMULATION_NAME}_finish
388 LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=hppaelf_create_output_section_statements