12159047fSniklas# This shell script emits a C file. -*- C -*-
2c074d1c9Sdrahn#   Copyright 1991, 1993, 1994, 1997, 1999, 2000, 2001, 2002, 2003
3b55d4692Sfgsch#   Free Software Foundation, Inc.
4b55d4692Sfgsch#
5b55d4692Sfgsch# This file is part of GLD, the Gnu Linker.
6b55d4692Sfgsch#
7b55d4692Sfgsch# This program is free software; you can redistribute it and/or modify
8b55d4692Sfgsch# it under the terms of the GNU General Public License as published by
9b55d4692Sfgsch# the Free Software Foundation; either version 2 of the License, or
10b55d4692Sfgsch# (at your option) any later version.
11b55d4692Sfgsch#
12b55d4692Sfgsch# This program is distributed in the hope that it will be useful,
13b55d4692Sfgsch# but WITHOUT ANY WARRANTY; without even the implied warranty of
14b55d4692Sfgsch# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15b55d4692Sfgsch# GNU General Public License for more details.
16b55d4692Sfgsch#
17b55d4692Sfgsch# You should have received a copy of the GNU General Public License
18b55d4692Sfgsch# along with this program; if not, write to the Free Software
19b55d4692Sfgsch# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20b55d4692Sfgsch#
212159047fSniklas
22b55d4692Sfgsch# This file is sourced from elf32.em, and defines extra hppa-elf
23b55d4692Sfgsch# specific routines.
24b55d4692Sfgsch#
25b55d4692Sfgschcat >>e${EMULATION_NAME}.c <<EOF
262159047fSniklas
272159047fSniklas#include "ldctor.h"
28b55d4692Sfgsch#include "elf32-hppa.h"
292159047fSniklas
30b55d4692Sfgsch
31b55d4692Sfgsch/* Fake input file for stubs.  */
322159047fSniklasstatic lang_input_statement_type *stub_file;
332159047fSniklas
34b55d4692Sfgsch/* Type of import/export stubs to build.  For a single sub-space model,
35b55d4692Sfgsch   we can build smaller import stubs and there is no need for export
36b55d4692Sfgsch   stubs.  */
37b55d4692Sfgschstatic int multi_subspace = 0;
382159047fSniklas
39c074d1c9Sdrahn/* Whether we need to call hppa_layout_sections_again.  */
40c074d1c9Sdrahnstatic int need_laying_out = 0;
41c074d1c9Sdrahn
42b55d4692Sfgsch/* Maximum size of a group of input sections that can be handled by
43b55d4692Sfgsch   one stub section.  A value of +/-1 indicates the bfd back-end
44b55d4692Sfgsch   should use a suitable default size.  */
45b55d4692Sfgschstatic bfd_signed_vma group_size = 1;
462159047fSniklas
47b55d4692Sfgsch/* Stops the linker merging .text sections on a relocatable link,
48b55d4692Sfgsch   and adds millicode library to the list of input files.  */
492159047fSniklas
502159047fSniklasstatic void
51*007c2a45Smiodhppaelf_after_parse (void)
522159047fSniklas{
53*007c2a45Smiod  if (link_info.relocatable)
54b55d4692Sfgsch    lang_add_unique (".text");
55c074d1c9Sdrahn#if 0 /* Enable this once we split millicode stuff from libgcc.  */
56b55d4692Sfgsch  else
57b55d4692Sfgsch    lang_add_input_file ("milli",
58b55d4692Sfgsch			 lang_input_file_is_l_enum,
59b55d4692Sfgsch			 NULL);
60b55d4692Sfgsch#endif
612159047fSniklas}
622159047fSniklas
632159047fSniklas/* This is called before the input files are opened.  We create a new
64b55d4692Sfgsch   fake input file to hold the stub sections.  */
652159047fSniklas
662159047fSniklasstatic void
67*007c2a45Smiodhppaelf_create_output_section_statements (void)
682159047fSniklas{
69*007c2a45Smiod  extern const bfd_target bfd_elf32_hppa_linux_vec;
70*007c2a45Smiod  extern const bfd_target bfd_elf32_hppa_vec;
71*007c2a45Smiod
72*007c2a45Smiod  if (link_info.hash->creator != &bfd_elf32_hppa_linux_vec
73*007c2a45Smiod      && link_info.hash->creator != &bfd_elf32_hppa_vec)
74*007c2a45Smiod    return;
75*007c2a45Smiod
762159047fSniklas  stub_file = lang_add_input_file ("linker stubs",
772159047fSniklas				   lang_input_file_is_fake_enum,
782159047fSniklas				   NULL);
792159047fSniklas  stub_file->the_bfd = bfd_create ("linker stubs", output_bfd);
802159047fSniklas  if (stub_file->the_bfd == NULL
812159047fSniklas      || ! bfd_set_arch_mach (stub_file->the_bfd,
822159047fSniklas			      bfd_get_arch (output_bfd),
832159047fSniklas			      bfd_get_mach (output_bfd)))
842159047fSniklas    {
852159047fSniklas      einfo ("%X%P: can not create BFD %E\n");
862159047fSniklas      return;
872159047fSniklas    }
882159047fSniklas
892159047fSniklas  ldlang_add_file (stub_file);
902159047fSniklas}
912159047fSniklas
92b55d4692Sfgsch
93b55d4692Sfgschstruct hook_stub_info
94b55d4692Sfgsch{
95b55d4692Sfgsch  lang_statement_list_type add;
96b55d4692Sfgsch  asection *input_section;
97b55d4692Sfgsch};
98b55d4692Sfgsch
99b55d4692Sfgsch/* Traverse the linker tree to find the spot where the stub goes.  */
100b55d4692Sfgsch
101c074d1c9Sdrahnstatic bfd_boolean
102*007c2a45Smiodhook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
103b55d4692Sfgsch{
104b55d4692Sfgsch  lang_statement_union_type *l;
105c074d1c9Sdrahn  bfd_boolean ret;
106b55d4692Sfgsch
107c074d1c9Sdrahn  for (; (l = *lp) != NULL; lp = &l->header.next)
108b55d4692Sfgsch    {
109b55d4692Sfgsch      switch (l->header.type)
110b55d4692Sfgsch	{
111b55d4692Sfgsch	case lang_constructors_statement_enum:
112b55d4692Sfgsch	  ret = hook_in_stub (info, &constructor_list.head);
113b55d4692Sfgsch	  if (ret)
114b55d4692Sfgsch	    return ret;
115b55d4692Sfgsch	  break;
116b55d4692Sfgsch
117b55d4692Sfgsch	case lang_output_section_statement_enum:
118b55d4692Sfgsch	  ret = hook_in_stub (info,
119b55d4692Sfgsch			      &l->output_section_statement.children.head);
120b55d4692Sfgsch	  if (ret)
121b55d4692Sfgsch	    return ret;
122b55d4692Sfgsch	  break;
123b55d4692Sfgsch
124b55d4692Sfgsch	case lang_wild_statement_enum:
125b55d4692Sfgsch	  ret = hook_in_stub (info, &l->wild_statement.children.head);
126b55d4692Sfgsch	  if (ret)
127b55d4692Sfgsch	    return ret;
128b55d4692Sfgsch	  break;
129b55d4692Sfgsch
130b55d4692Sfgsch	case lang_group_statement_enum:
131b55d4692Sfgsch	  ret = hook_in_stub (info, &l->group_statement.children.head);
132b55d4692Sfgsch	  if (ret)
133b55d4692Sfgsch	    return ret;
134b55d4692Sfgsch	  break;
135b55d4692Sfgsch
136b55d4692Sfgsch	case lang_input_section_enum:
137b55d4692Sfgsch	  if (l->input_section.section == info->input_section)
138b55d4692Sfgsch	    {
139b55d4692Sfgsch	      /* We've found our section.  Insert the stub immediately
140b55d4692Sfgsch		 before its associated input section.  */
141b55d4692Sfgsch	      *lp = info->add.head;
142b55d4692Sfgsch	      *(info->add.tail) = l;
143c074d1c9Sdrahn	      return TRUE;
144b55d4692Sfgsch	    }
145b55d4692Sfgsch	  break;
146b55d4692Sfgsch
147b55d4692Sfgsch	case lang_data_statement_enum:
148b55d4692Sfgsch	case lang_reloc_statement_enum:
149b55d4692Sfgsch	case lang_object_symbols_statement_enum:
150b55d4692Sfgsch	case lang_output_statement_enum:
151b55d4692Sfgsch	case lang_target_statement_enum:
152b55d4692Sfgsch	case lang_input_statement_enum:
153b55d4692Sfgsch	case lang_assignment_statement_enum:
154b55d4692Sfgsch	case lang_padding_statement_enum:
155b55d4692Sfgsch	case lang_address_statement_enum:
156b55d4692Sfgsch	case lang_fill_statement_enum:
157b55d4692Sfgsch	  break;
158b55d4692Sfgsch
159b55d4692Sfgsch	default:
160b55d4692Sfgsch	  FAIL ();
161b55d4692Sfgsch	  break;
162b55d4692Sfgsch	}
163b55d4692Sfgsch    }
164c074d1c9Sdrahn  return FALSE;
165b55d4692Sfgsch}
166b55d4692Sfgsch
167b55d4692Sfgsch
168b55d4692Sfgsch/* Call-back for elf32_hppa_size_stubs.  */
169b55d4692Sfgsch
170b55d4692Sfgsch/* Create a new stub section, and arrange for it to be linked
171b55d4692Sfgsch   immediately before INPUT_SECTION.  */
172b55d4692Sfgsch
173b55d4692Sfgschstatic asection *
174*007c2a45Smiodhppaelf_add_stub_section (const char *stub_sec_name, asection *input_section)
175b55d4692Sfgsch{
176b55d4692Sfgsch  asection *stub_sec;
177b55d4692Sfgsch  flagword flags;
178b55d4692Sfgsch  asection *output_section;
179b55d4692Sfgsch  const char *secname;
180b55d4692Sfgsch  lang_output_section_statement_type *os;
181b55d4692Sfgsch  struct hook_stub_info info;
182b55d4692Sfgsch
183b55d4692Sfgsch  stub_sec = bfd_make_section_anyway (stub_file->the_bfd, stub_sec_name);
184b55d4692Sfgsch  if (stub_sec == NULL)
185b55d4692Sfgsch    goto err_ret;
186b55d4692Sfgsch
187b55d4692Sfgsch  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
188b55d4692Sfgsch	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
189b55d4692Sfgsch  if (!bfd_set_section_flags (stub_file->the_bfd, stub_sec, flags))
190b55d4692Sfgsch    goto err_ret;
191b55d4692Sfgsch
192b55d4692Sfgsch  output_section = input_section->output_section;
193b55d4692Sfgsch  secname = bfd_get_section_name (output_section->owner, output_section);
194b55d4692Sfgsch  os = lang_output_section_find (secname);
195b55d4692Sfgsch
196b55d4692Sfgsch  info.input_section = input_section;
197b55d4692Sfgsch  lang_list_init (&info.add);
198c074d1c9Sdrahn  lang_add_section (&info.add, stub_sec, os, stub_file);
199b55d4692Sfgsch
200b55d4692Sfgsch  if (info.add.head == NULL)
201b55d4692Sfgsch    goto err_ret;
202b55d4692Sfgsch
203b55d4692Sfgsch  if (hook_in_stub (&info, &os->children.head))
204b55d4692Sfgsch    return stub_sec;
205b55d4692Sfgsch
206b55d4692Sfgsch err_ret:
207b55d4692Sfgsch  einfo ("%X%P: can not make stub section: %E\n");
208b55d4692Sfgsch  return NULL;
209b55d4692Sfgsch}
210b55d4692Sfgsch
211b55d4692Sfgsch
212b55d4692Sfgsch/* Another call-back for elf32_hppa_size_stubs.  */
2132159047fSniklas
2142159047fSniklasstatic void
215*007c2a45Smiodhppaelf_layout_sections_again (void)
2162159047fSniklas{
217b55d4692Sfgsch  /* If we have changed sizes of the stub sections, then we need
218b55d4692Sfgsch     to recalculate all the section offsets.  This may mean we need to
219b55d4692Sfgsch     add even more stubs.  */
220c074d1c9Sdrahn  need_laying_out = 0;
2212159047fSniklas
222c074d1c9Sdrahn  lang_reset_memory_regions ();
2232159047fSniklas
2242159047fSniklas  /* Resize the sections.  */
2252159047fSniklas  lang_size_sections (stat_ptr->head, abs_output_section,
226c074d1c9Sdrahn		      &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
2272159047fSniklas
2282159047fSniklas  /* Redo special stuff.  */
2292159047fSniklas  ldemul_after_allocation ();
2302159047fSniklas
2312159047fSniklas  /* Do the assignments again.  */
232b55d4692Sfgsch  lang_do_assignments (stat_ptr->head, abs_output_section,
233c074d1c9Sdrahn		       (fill_type *) 0, (bfd_vma) 0);
234c074d1c9Sdrahn}
235c074d1c9Sdrahn
236c074d1c9Sdrahn
237c074d1c9Sdrahnstatic void
238*007c2a45Smiodbuild_section_lists (lang_statement_union_type *statement)
239c074d1c9Sdrahn{
240c074d1c9Sdrahn  if (statement->header.type == lang_input_section_enum
241c074d1c9Sdrahn      && !statement->input_section.ifile->just_syms_flag
242c074d1c9Sdrahn      && statement->input_section.section->output_section != NULL
243c074d1c9Sdrahn      && statement->input_section.section->output_section->owner == output_bfd)
244c074d1c9Sdrahn    {
245c074d1c9Sdrahn      elf32_hppa_next_input_section (&link_info,
246c074d1c9Sdrahn				     statement->input_section.section);
247c074d1c9Sdrahn    }
248b55d4692Sfgsch}
2492159047fSniklas
250b55d4692Sfgsch
251b55d4692Sfgsch/* Final emulation specific call.  For the PA we use this opportunity
252b55d4692Sfgsch   to build linker stubs.  */
253b55d4692Sfgsch
254b55d4692Sfgschstatic void
255*007c2a45Smiodgld${EMULATION_NAME}_finish (void)
2562159047fSniklas{
257*007c2a45Smiod  /* bfd_elf_discard_info just plays with debugging sections,
258c074d1c9Sdrahn     ie. doesn't affect any code, so we can delay resizing the
259c074d1c9Sdrahn     sections.  It's likely we'll resize everything in the process of
260c074d1c9Sdrahn     adding stubs.  */
261*007c2a45Smiod  if (bfd_elf_discard_info (output_bfd, &link_info))
262c074d1c9Sdrahn    need_laying_out = 1;
263c074d1c9Sdrahn
264b55d4692Sfgsch  /* If generating a relocatable output file, then we don't
265b55d4692Sfgsch     have to examine the relocs.  */
266*007c2a45Smiod  if (stub_file != NULL && !link_info.relocatable)
267c074d1c9Sdrahn    {
268c074d1c9Sdrahn      int ret = elf32_hppa_setup_section_lists (output_bfd, &link_info);
269c074d1c9Sdrahn
270c074d1c9Sdrahn      if (ret != 0)
271c074d1c9Sdrahn	{
272c074d1c9Sdrahn	  if (ret < 0)
273c074d1c9Sdrahn	    {
274c074d1c9Sdrahn	      einfo ("%X%P: can not size stub section: %E\n");
275b55d4692Sfgsch	      return;
276c074d1c9Sdrahn	    }
277c074d1c9Sdrahn
278c074d1c9Sdrahn	  lang_for_each_statement (build_section_lists);
279b55d4692Sfgsch
280b55d4692Sfgsch	  /* Call into the BFD backend to do the real work.  */
281b55d4692Sfgsch	  if (! elf32_hppa_size_stubs (output_bfd,
282b55d4692Sfgsch				       stub_file->the_bfd,
283b55d4692Sfgsch				       &link_info,
284b55d4692Sfgsch				       multi_subspace,
285b55d4692Sfgsch				       group_size,
286b55d4692Sfgsch				       &hppaelf_add_stub_section,
287c074d1c9Sdrahn				       &hppaelf_layout_sections_again))
288b55d4692Sfgsch	    {
289b55d4692Sfgsch	      einfo ("%X%P: can not size stub section: %E\n");
2902159047fSniklas	      return;
2912159047fSniklas	    }
292c074d1c9Sdrahn	}
293c074d1c9Sdrahn    }
294b55d4692Sfgsch
295c074d1c9Sdrahn  if (need_laying_out)
296c074d1c9Sdrahn    hppaelf_layout_sections_again ();
297c074d1c9Sdrahn
298*007c2a45Smiod  if (! link_info.relocatable)
299c074d1c9Sdrahn    {
300b55d4692Sfgsch      /* Set the global data pointer.  */
301b55d4692Sfgsch      if (! elf32_hppa_set_gp (output_bfd, &link_info))
302b55d4692Sfgsch	{
303b55d4692Sfgsch	  einfo ("%X%P: can not set gp\n");
304b55d4692Sfgsch	  return;
305b55d4692Sfgsch	}
306b55d4692Sfgsch
307b55d4692Sfgsch      /* Now build the linker stubs.  */
308*007c2a45Smiod      if (stub_file != NULL && stub_file->the_bfd->sections != NULL)
309b55d4692Sfgsch	{
310b55d4692Sfgsch	  if (! elf32_hppa_build_stubs (&link_info))
311b55d4692Sfgsch	    einfo ("%X%P: can not build stubs: %E\n");
3122159047fSniklas	}
3132159047fSniklas    }
314c074d1c9Sdrahn}
3152159047fSniklas
3162159047fSniklas
317b55d4692Sfgsch/* Avoid processing the fake stub_file in vercheck, stat_needed and
318b55d4692Sfgsch   check_needed routines.  */
3192159047fSniklas
320*007c2a45Smiodstatic void (*real_func) (lang_input_statement_type *);
3212159047fSniklas
322*007c2a45Smiodstatic void hppa_for_each_input_file_wrapper (lang_input_statement_type *l)
3232159047fSniklas{
324b55d4692Sfgsch  if (l != stub_file)
325b55d4692Sfgsch    (*real_func) (l);
3262159047fSniklas}
3272159047fSniklas
328b55d4692Sfgschstatic void
329*007c2a45Smiodhppa_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
3302159047fSniklas{
331b55d4692Sfgsch  real_func = func;
332b55d4692Sfgsch  lang_for_each_input_file (&hppa_for_each_input_file_wrapper);
333b55d4692Sfgsch}
334b55d4692Sfgsch
335b55d4692Sfgsch#define lang_for_each_input_file hppa_lang_for_each_input_file
336b55d4692Sfgsch
3372159047fSniklasEOF
338b55d4692Sfgsch
339b55d4692Sfgsch# Define some shell vars to insert bits of code into the standard elf
340b55d4692Sfgsch# parse_args and list_options functions.
341b55d4692Sfgsch#
342b55d4692SfgschPARSE_AND_LIST_PROLOGUE='
343b55d4692Sfgsch#define OPTION_MULTI_SUBSPACE		301
344b55d4692Sfgsch#define OPTION_STUBGROUP_SIZE		(OPTION_MULTI_SUBSPACE + 1)
345b55d4692Sfgsch'
346b55d4692Sfgsch
347b55d4692SfgschPARSE_AND_LIST_LONGOPTS='
348b55d4692Sfgsch  { "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE },
349b55d4692Sfgsch  { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
350b55d4692Sfgsch'
351b55d4692Sfgsch
352b55d4692SfgschPARSE_AND_LIST_OPTIONS='
353b55d4692Sfgsch  fprintf (file, _("\
354b55d4692Sfgsch  --multi-subspace      Generate import and export stubs to support\n\
355b55d4692Sfgsch                          multiple sub-space shared libraries\n"
356b55d4692Sfgsch		   ));
357b55d4692Sfgsch  fprintf (file, _("\
358b55d4692Sfgsch  --stub-group-size=N   Maximum size of a group of input sections that can be\n\
359b55d4692Sfgsch                          handled by one stub section.  A negative value\n\
360b55d4692Sfgsch                          locates all stubs before their branches (with a\n\
361b55d4692Sfgsch                          group size of -N), while a positive value allows\n\
362b55d4692Sfgsch                          two groups of input sections, one before, and one\n\
363b55d4692Sfgsch                          after each stub section.  Values of +/-1 indicate\n\
364c074d1c9Sdrahn                          the linker should choose suitable defaults.\n"
365b55d4692Sfgsch		   ));
366b55d4692Sfgsch'
367b55d4692Sfgsch
368b55d4692SfgschPARSE_AND_LIST_ARGS_CASES='
369b55d4692Sfgsch    case OPTION_MULTI_SUBSPACE:
370b55d4692Sfgsch      multi_subspace = 1;
371b55d4692Sfgsch      break;
372b55d4692Sfgsch
373b55d4692Sfgsch    case OPTION_STUBGROUP_SIZE:
374b55d4692Sfgsch      {
375b55d4692Sfgsch	const char *end;
376b55d4692Sfgsch        group_size = bfd_scan_vma (optarg, &end, 0);
377b55d4692Sfgsch        if (*end)
378b55d4692Sfgsch	  einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
379b55d4692Sfgsch      }
380b55d4692Sfgsch      break;
381b55d4692Sfgsch'
382b55d4692Sfgsch
383b55d4692Sfgsch# Put these extra hppaelf routines in ld_${EMULATION_NAME}_emulation
384b55d4692Sfgsch#
385b55d4692SfgschLDEMUL_AFTER_PARSE=hppaelf_after_parse
386c074d1c9SdrahnLDEMUL_FINISH=gld${EMULATION_NAME}_finish
387b55d4692SfgschLDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=hppaelf_create_output_section_statements
388