ppc64elf.em revision 104834
1# This shell script emits a C file. -*- C -*-
2#   Copyright 2002 Free Software Foundation, Inc.
3#
4# This file is part of GLD, the Gnu Linker.
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19#
20
21# This file is sourced from elf32.em, and defines extra powerpc64-elf
22# specific routines.
23#
24cat >>e${EMULATION_NAME}.c <<EOF
25
26#include "ldctor.h"
27#include "libbfd.h"
28#include "elf64-ppc.h"
29
30/* Fake input file for stubs.  */
31static lang_input_statement_type *stub_file;
32
33/* Whether we need to call ppc_layout_sections_again.  */
34static int need_laying_out = 0;
35
36/* Maximum size of a group of input sections that can be handled by
37   one stub section.  A value of +/-1 indicates the bfd back-end
38   should use a suitable default size.  */
39static bfd_signed_vma group_size = 1;
40
41/* Whether to add ".foo" entries for each "foo" in a version script.  */
42static int dotsyms = 1;
43
44static void ppc_create_output_section_statements PARAMS ((void));
45static void ppc_after_open PARAMS ((void));
46static asection *ppc_add_stub_section PARAMS ((const char *, asection *));
47static void ppc_layout_sections_again PARAMS ((void));
48static void gld${EMULATION_NAME}_after_allocation PARAMS ((void));
49static void build_section_lists PARAMS ((lang_statement_union_type *));
50static struct bfd_elf_version_expr *gld${EMULATION_NAME}_new_vers_pattern
51  PARAMS ((struct bfd_elf_version_expr *));
52
53/* This is called before the input files are opened.  We create a new
54   fake input file to hold the stub sections.  */
55
56static void
57ppc_create_output_section_statements ()
58{
59  stub_file = lang_add_input_file ("linker stubs",
60				   lang_input_file_is_fake_enum,
61				   NULL);
62  stub_file->the_bfd = bfd_create ("linker stubs", output_bfd);
63  if (stub_file->the_bfd == NULL
64      || !bfd_set_arch_mach (stub_file->the_bfd,
65			     bfd_get_arch (output_bfd),
66			     bfd_get_mach (output_bfd)))
67    {
68      einfo ("%X%P: can not create BFD %E\n");
69      return;
70    }
71
72  ldlang_add_file (stub_file);
73}
74
75static void
76ppc_after_open ()
77{
78  if (!ppc64_elf_mark_entry_syms (&link_info))
79    {
80      einfo ("%X%P: can not mark entry symbols %E\n");
81      return;
82    }
83
84  gld${EMULATION_NAME}_after_open ();
85}
86
87struct hook_stub_info
88{
89  lang_statement_list_type add;
90  asection *input_section;
91};
92
93/* Traverse the linker tree to find the spot where the stub goes.  */
94
95static boolean hook_in_stub
96  PARAMS ((struct hook_stub_info *, lang_statement_union_type **));
97
98static boolean
99hook_in_stub (info, lp)
100     struct hook_stub_info *info;
101     lang_statement_union_type **lp;
102{
103  lang_statement_union_type *l;
104  boolean ret;
105
106  for (; (l = *lp) != NULL; lp = &l->header.next)
107    {
108      switch (l->header.type)
109	{
110	case lang_constructors_statement_enum:
111	  ret = hook_in_stub (info, &constructor_list.head);
112	  if (ret)
113	    return ret;
114	  break;
115
116	case lang_output_section_statement_enum:
117	  ret = hook_in_stub (info,
118			      &l->output_section_statement.children.head);
119	  if (ret)
120	    return ret;
121	  break;
122
123	case lang_wild_statement_enum:
124	  ret = hook_in_stub (info, &l->wild_statement.children.head);
125	  if (ret)
126	    return ret;
127	  break;
128
129	case lang_group_statement_enum:
130	  ret = hook_in_stub (info, &l->group_statement.children.head);
131	  if (ret)
132	    return ret;
133	  break;
134
135	case lang_input_section_enum:
136	  if (l->input_section.section == info->input_section)
137	    {
138	      /* We've found our section.  Insert the stub immediately
139		 before its associated input section.  */
140	      *lp = info->add.head;
141	      *(info->add.tail) = l;
142	      return true;
143	    }
144	  break;
145
146	case lang_data_statement_enum:
147	case lang_reloc_statement_enum:
148	case lang_object_symbols_statement_enum:
149	case lang_output_statement_enum:
150	case lang_target_statement_enum:
151	case lang_input_statement_enum:
152	case lang_assignment_statement_enum:
153	case lang_padding_statement_enum:
154	case lang_address_statement_enum:
155	case lang_fill_statement_enum:
156	  break;
157
158	default:
159	  FAIL ();
160	  break;
161	}
162    }
163  return false;
164}
165
166
167/* Call-back for ppc64_elf_size_stubs.  */
168
169/* Create a new stub section, and arrange for it to be linked
170   immediately before INPUT_SECTION.  */
171
172static asection *
173ppc_add_stub_section (stub_sec_name, input_section)
174     const char *stub_sec_name;
175     asection *input_section;
176{
177  asection *stub_sec;
178  flagword flags;
179  asection *output_section;
180  const char *secname;
181  lang_output_section_statement_type *os;
182  struct hook_stub_info info;
183
184  stub_sec = bfd_make_section_anyway (stub_file->the_bfd, stub_sec_name);
185  if (stub_sec == NULL)
186    goto err_ret;
187
188  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
189	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
190  if (!bfd_set_section_flags (stub_file->the_bfd, stub_sec, flags))
191    goto err_ret;
192
193  output_section = input_section->output_section;
194  secname = bfd_get_section_name (output_section->owner, output_section);
195  os = lang_output_section_find (secname);
196
197  info.input_section = input_section;
198  lang_list_init (&info.add);
199  lang_add_section (&info.add, stub_sec, os, stub_file);
200
201  if (info.add.head == NULL)
202    goto err_ret;
203
204  if (hook_in_stub (&info, &os->children.head))
205    return stub_sec;
206
207 err_ret:
208  einfo ("%X%P: can not make stub section: %E\n");
209  return NULL;
210}
211
212
213/* Another call-back for ppc64_elf_size_stubs.  */
214
215static void
216ppc_layout_sections_again ()
217{
218  /* If we have changed sizes of the stub sections, then we need
219     to recalculate all the section offsets.  This may mean we need to
220     add even more stubs.  */
221  need_laying_out = 0;
222
223  lang_reset_memory_regions ();
224
225  /* Resize the sections.  */
226  lang_size_sections (stat_ptr->head, abs_output_section,
227		      &stat_ptr->head, 0, (bfd_vma) 0, NULL);
228
229  /* Recalculate TOC base.  */
230  ldemul_after_allocation ();
231
232  /* Do the assignments again.  */
233  lang_do_assignments (stat_ptr->head, abs_output_section,
234		       (fill_type *) 0, (bfd_vma) 0);
235}
236
237
238/* Call the back-end function to set TOC base after we have placed all
239   the sections.  */
240static void
241gld${EMULATION_NAME}_after_allocation ()
242{
243  if (!link_info.relocateable)
244    _bfd_set_gp_value (output_bfd, ppc64_elf_toc (output_bfd));
245}
246
247
248static void
249build_section_lists (statement)
250     lang_statement_union_type *statement;
251{
252  if (statement->header.type == lang_input_section_enum
253      && !statement->input_section.ifile->just_syms_flag
254      && statement->input_section.section->output_section != NULL
255      && statement->input_section.section->output_section->owner == output_bfd)
256    {
257      ppc64_elf_next_input_section (&link_info,
258				    statement->input_section.section);
259    }
260}
261
262
263/* Final emulation specific call.  */
264
265static void
266gld${EMULATION_NAME}_finish ()
267{
268  int ret;
269
270  /* e_entry on PowerPC64 points to the function descriptor for
271     _start.  If _start is missing, default to the first function
272     descriptor in the .opd section.  */
273  entry_section = ".opd";
274
275  /* If generating a relocatable output file, then we don't have any
276     stubs.  */
277  if (link_info.relocateable)
278    return;
279
280  /* bfd_elf64_discard_info just plays with debugging sections,
281     ie. doesn't affect any code, so we can delay resizing the
282     sections.  It's likely we'll resize everything in the process of
283     adding stubs.  */
284  if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info))
285    need_laying_out = 1;
286
287  ret = ppc64_elf_setup_section_lists (output_bfd, &link_info);
288  if (ret != 0)
289    {
290      if (ret < 0)
291	{
292	  einfo ("%X%P: can not size stub section: %E\n");
293	  return;
294	}
295
296      lang_for_each_statement (build_section_lists);
297
298      /* Call into the BFD backend to do the real work.  */
299      if (!ppc64_elf_size_stubs (output_bfd,
300				 stub_file->the_bfd,
301				 &link_info,
302				 group_size,
303				 &ppc_add_stub_section,
304				 &ppc_layout_sections_again))
305	{
306	  einfo ("%X%P: can not size stub section: %E\n");
307	  return;
308	}
309    }
310
311  if (need_laying_out)
312    ppc_layout_sections_again ();
313
314  if (stub_file->the_bfd->sections != NULL)
315    {
316      if (!ppc64_elf_build_stubs (&link_info))
317	einfo ("%X%P: can not build stubs: %E\n");
318    }
319}
320
321
322/* Add a pattern matching ".foo" for every "foo" in a version script.
323
324   The reason for doing this is that many shared library version
325   scripts export a selected set of functions or data symbols, forcing
326   others local.  eg.
327
328   . VERS_1 {
329   .       global:
330   .               this; that; some; thing;
331   .       local:
332   .               *;
333   .   };
334
335   To make the above work for PowerPC64, we need to export ".this",
336   ".that" and so on, otherwise only the function descriptor syms are
337   exported.  Lack of an exported function code sym may cause a
338   definition to be pulled in from a static library.  */
339
340struct bfd_elf_version_expr *
341gld${EMULATION_NAME}_new_vers_pattern (entry)
342     struct bfd_elf_version_expr *entry;
343{
344  struct bfd_elf_version_expr *dot_entry;
345  struct bfd_elf_version_expr *next;
346  unsigned int len;
347  char *dot_pat;
348
349  if (!dotsyms || entry->pattern[0] == '*')
350    return entry;
351
352  /* Is the script adding ".foo" explicitly?  */
353  if (entry->pattern[0] == '.')
354    {
355      /* We may have added this pattern automatically.  Don't add it
356	 again.  Quadratic behaviour here is acceptable as the list
357	 may be traversed for each input bfd symbol.  */
358      for (next = entry->next; next != NULL; next = next->next)
359	{
360	  if (strcmp (next->pattern, entry->pattern) == 0
361	      && next->match == entry->match)
362	    {
363	      next = entry->next;
364	      free ((char *) entry->pattern);
365	      free (entry);
366	      return next;
367	    }
368	}
369      return entry;
370    }
371
372  /* Don't add ".foo" if the script has already done so.  */
373  for (next = entry->next; next != NULL; next = next->next)
374    {
375      if (next->pattern[0] == '.'
376	  && strcmp (next->pattern + 1, entry->pattern) == 0
377	  && next->match == entry->match)
378	return entry;
379    }
380
381  dot_entry = (struct bfd_elf_version_expr *) xmalloc (sizeof *dot_entry);
382  dot_entry->next = entry;
383  len = strlen (entry->pattern) + 2;
384  dot_pat = xmalloc (len);
385  dot_pat[0] = '.';
386  memcpy (dot_pat + 1, entry->pattern, len - 1);
387  dot_entry->pattern = dot_pat;
388  dot_entry->match = entry->match;
389  return dot_entry;
390}
391
392
393/* Avoid processing the fake stub_file in vercheck, stat_needed and
394   check_needed routines.  */
395
396static void ppc_for_each_input_file_wrapper
397  PARAMS ((lang_input_statement_type *));
398static void ppc_lang_for_each_input_file
399  PARAMS ((void (*) (lang_input_statement_type *)));
400
401static void (*real_func) PARAMS ((lang_input_statement_type *));
402
403static void ppc_for_each_input_file_wrapper (l)
404     lang_input_statement_type *l;
405{
406  if (l != stub_file)
407    (*real_func) (l);
408}
409
410static void
411ppc_lang_for_each_input_file (func)
412     void (*func) PARAMS ((lang_input_statement_type *));
413{
414  real_func = func;
415  lang_for_each_input_file (&ppc_for_each_input_file_wrapper);
416}
417
418#define lang_for_each_input_file ppc_lang_for_each_input_file
419
420EOF
421
422# Define some shell vars to insert bits of code into the standard elf
423# parse_args and list_options functions.
424#
425PARSE_AND_LIST_PROLOGUE='
426#define OPTION_STUBGROUP_SIZE		301
427#define OPTION_DOTSYMS			(OPTION_STUBGROUP_SIZE + 1)
428#define OPTION_NO_DOTSYMS		(OPTION_DOTSYMS + 1)
429'
430
431# The options are repeated below so that no abbreviations are allowed.
432# Otherwise -s matches stub-group-size
433PARSE_AND_LIST_LONGOPTS='
434  { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
435  { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
436  { "dotsyms", no_argument, NULL, OPTION_DOTSYMS },
437  { "dotsyms", no_argument, NULL, OPTION_DOTSYMS },
438  { "no-dotsyms", no_argument, NULL, OPTION_NO_DOTSYMS },
439  { "no-dotsyms", no_argument, NULL, OPTION_NO_DOTSYMS },
440'
441
442PARSE_AND_LIST_OPTIONS='
443  fprintf (file, _("\
444  --stub-group-size=N   Maximum size of a group of input sections that can be\n\
445                          handled by one stub section.  A negative value\n\
446                          locates all stubs before their branches (with a\n\
447                          group size of -N), while a positive value allows\n\
448                          two groups of input sections, one before, and one\n\
449                          after each stub section.  Values of +/-1 indicate\n\
450                          the linker should choose suitable defaults.\n"
451		   ));
452  fprintf (file, _("\
453  --dotsyms             For every version pattern \"foo\" in a version script,\n\
454                          add \".foo\" so that function code symbols are\n\
455                          treated the same as function descriptor symbols.\n\
456                          Defaults to on.\n"
457		   ));
458  fprintf (file, _("\
459  --no-dotsyms          Don'\''t do anything special in version scripts.\n"
460		   ));
461'
462
463PARSE_AND_LIST_ARGS_CASES='
464    case OPTION_STUBGROUP_SIZE:
465      {
466	const char *end;
467        group_size = bfd_scan_vma (optarg, &end, 0);
468        if (*end)
469	  einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
470      }
471      break;
472
473    case OPTION_DOTSYMS:
474      {
475	dotsyms = 1;
476      }
477      break;
478
479    case OPTION_NO_DOTSYMS:
480      {
481	dotsyms = 0;
482      }
483      break;
484'
485
486# Put these extra ppc64elf routines in ld_${EMULATION_NAME}_emulation
487#
488LDEMUL_AFTER_OPEN=ppc_after_open
489LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
490LDEMUL_FINISH=gld${EMULATION_NAME}_finish
491LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=ppc_create_output_section_statements
492LDEMUL_NEW_VERS_PATTERN=gld${EMULATION_NAME}_new_vers_pattern
493