1 # This shell script emits a C file. -*- C -*-
2 # It does some substitutions.
3 cat >e${EMULATION_NAME}.c <<EOF
4 /* This file is is generated by a shell script. DO NOT EDIT! */
6 /* SunOS emulation code for ${EMULATION_NAME}
7 Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
8 Written by Steve Chamberlain <sac@cygnus.com>
9 SunOS shared library support by Ian Lance Taylor <ian@cygnus.com>
11 This file is part of GLD, the Gnu Linker.
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27 #define TARGET_IS_${EMULATION_NAME}
29 #include <sys/types.h>
32 /* FIXME: On some hosts we will need to include a different file.
33 This is correct for SunOS, which is the only place this file will
34 typically be compiled. However, if somebody configures the linker
35 for all targets, they will run into trouble here. */
51 static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
52 static void gld${EMULATION_NAME}_create_output_section_statements
54 static void gld${EMULATION_NAME}_find_so
55 PARAMS ((lang_input_statement_type *));
56 static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
57 static void gld${EMULATION_NAME}_find_statement_assignment
58 PARAMS ((lang_statement_union_type *));
59 static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
60 static void gld${EMULATION_NAME}_count_need
61 PARAMS ((lang_input_statement_type *));
62 static void gld${EMULATION_NAME}_set_need
63 PARAMS ((lang_input_statement_type *));
64 static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
67 gld${EMULATION_NAME}_before_parse()
69 ldfile_output_architecture = bfd_arch_${ARCH};
70 config.dynamic_link = true;
73 /* Despite the name, we use this routine to search for dynamic
74 libraries. On SunOS this requires a directory search. We need to
75 find the .so file with the highest version number. The user may
76 restrict the major version by saying, e.g., -lc.1. Also, if we
77 find a .so file, we need to look for a the same file after
78 replacing .so with .sa; if it exists, it will be an archive which
79 provide some initializations for data symbols, and we need to
80 search it after including the .so file. */
83 gld${EMULATION_NAME}_create_output_section_statements ()
85 if (config.dynamic_link)
86 lang_for_each_input_file (gld${EMULATION_NAME}_find_so);
89 /* Search the directory for a .so file for each library search. */
92 gld${EMULATION_NAME}_find_so (inp)
93 lang_input_statement_type *inp;
95 search_dirs_type *search;
101 int max_maj, max_min;
103 boolean found_static;
106 if (! inp->search_dirs_flag
107 || ! inp->is_archive)
110 ASSERT (strncmp (inp->local_sym_name, "-l", 2) == 0);
112 filename = inp->filename;
114 dot = strchr (filename, '.');
116 len = strlen (filename);
119 force_maj = atoi (dot + 1);
120 len = dot - filename;
121 alc = (char *) alloca (len + 1);
122 strncpy (alc, filename, len);
128 found_static = false;
129 max_maj = max_min = 0;
130 for (search = search_head; search != NULL; search = search->next)
133 struct dirent *entry;
135 dir = opendir (search->name);
139 while ((entry = readdir (dir)) != NULL)
141 int found_maj, found_min;
143 if (strncmp (entry->d_name, "lib", 3) != 0
144 || strncmp (entry->d_name + 3, inp->filename, len) != 0)
148 && strncmp (entry->d_name + 3 + len, ".a", 2) == 0)
154 if (strncmp (entry->d_name + 3 + len, ".so", 3) != 0)
157 /* We've found a .so file. Work out the major and minor
161 sscanf (entry->d_name + 3 + len, ".so.%d.%d",
162 &found_maj, &found_min);
164 if (force_maj != -1 && force_maj != found_maj)
167 /* We've found a match for the name we are searching for.
168 See if this is the version we should use. If the major
169 and minor versions match, we use the last entry in
170 alphabetical order; I don't know if this is how SunOS
171 distinguishes libc.so.1.8 from libc.so.1.8.1, but it
174 || (found_maj > max_maj)
175 || (found_maj == max_maj
176 && (found_min > max_min
177 || (found_min == max_min
178 && strcmp (entry->d_name, found) > 0))))
182 found = (char *) xmalloc (strlen (entry->d_name) + 1);
183 strcpy (found, entry->d_name);
191 if (found != NULL || found_static)
197 /* We did not find a matching .so file. This isn't an error,
198 since there might still be a matching .a file, which will be
199 found by the usual search. */
203 /* Replace the filename with the one we have found. */
204 alc = (char *) xmalloc (strlen (search->name) + strlen (found) + 2);
205 sprintf (alc, "%s/%s", search->name, found);
208 /* Turn off the search_dirs_flag to prevent ldfile_open_file from
209 searching for this file again. */
210 inp->search_dirs_flag = false;
214 /* Now look for the same file name, but with .sa instead of .so. If
215 found, add it to the list of input files. */
216 alc = (char *) alloca (strlen (inp->filename) + 1);
217 strcpy (alc, inp->filename);
218 strstr (alc, ".so.")[2] = 'a';
219 if (stat (alc, &st) == 0)
221 lang_input_statement_type *sa;
224 /* Add the .sa file to the statement list just after the .so
225 file. This is really a hack. */
226 sa = ((lang_input_statement_type *)
227 xmalloc (sizeof (lang_input_statement_type)));
228 sa->header.next = inp->header.next;
229 sa->header.type = lang_input_statement_enum;
230 a = (char *) xmalloc (strlen (alc) + 1);
233 sa->local_sym_name = a;
236 sa->symbol_count = 0;
238 sa->next_real_file = inp->next_real_file;
239 sa->is_archive = false;
240 sa->search_dirs_flag = false;
241 sa->just_syms_flag = false;
244 sa->complained = false;
246 /* Put the new statement next on the list of statements and next
247 on the list of input files. */
248 inp->header.next = (lang_statement_union_type *) sa;
249 inp->next_real_file = (lang_statement_union_type *) sa;
253 /* We need to use static variables to pass information around the call
254 to lang_for_each_input_file. Ick. */
256 static bfd_size_type need_size;
257 static bfd_size_type need_entries;
258 static bfd_byte *need_contents;
259 static bfd_byte *need_pinfo;
260 static bfd_byte *need_pnames;
262 /* The size of one entry in the .need section, not including the file
265 #define NEED_ENTRY_SIZE (16)
267 /* This is called after the sections have been attached to output
268 sections, but before any sizes or addresses have been set. */
271 gld${EMULATION_NAME}_before_allocation ()
273 struct bfd_link_hash_entry *h = NULL;
278 /* We need to create a __DYNAMIC symbol. We don't do this in the
279 linker script because we want to set the value to the start of
280 the dynamic section if there is one, or to zero if there isn't
281 one. We need to create the symbol before calling
282 size_dynamic_sections, although we can't set the value until
284 if (! link_info.relocateable)
286 h = bfd_link_hash_lookup (link_info.hash, "__DYNAMIC", true, false,
289 einfo ("%P%F: bfd_link_hash_lookup: %E\n");
290 if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
292 einfo ("%P%F: failed to record assignment to __DYNAMIC: %E\n");
295 /* If we are going to make any variable assignments, we need to let
296 the backend linker know about them in case the variables are
297 referred to by dynamic objects. */
298 lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
300 /* Let the backend linker work out the sizes of any sections
301 required by dynamic linking. */
302 if (! bfd_sunos_size_dynamic_sections (output_bfd, &link_info, &sdyn,
304 einfo ("%P%F: failed to set dynamic section sizes: %E\n");
308 /* Set up the .need section. See the description of the ld_need
309 field in include/aout/sun4.h. */
314 lang_for_each_input_file (gld${EMULATION_NAME}_count_need);
316 /* We should only have a .need section if we have at least one
318 ASSERT (need_entries != 0);
320 sneed->_raw_size = need_size;
321 sneed->contents = (bfd_byte *) xmalloc (need_size);
323 need_contents = sneed->contents;
324 need_pinfo = sneed->contents;
325 need_pnames = sneed->contents + need_entries * 16;
327 lang_for_each_input_file (gld${EMULATION_NAME}_set_need);
329 ASSERT (need_pnames - sneed->contents == need_size);
335 search_dirs_type *search;
337 /* Set up the .rules section. This is just a PATH like string
338 of the -L arguments given on the command line. */
340 for (search = search_head; search != NULL; search = search->next)
342 size += strlen (search->name) + 1;
343 srules->_raw_size = size;
348 srules->contents = (bfd_byte *) xmalloc (size);
349 p = (char *) srules->contents;
351 for (search = search_head; search != NULL; search = search->next)
355 if (p != (char *) srules->contents)
357 strcpy (p, search->name);
364 /* We must assign a value to __DYNAMIC. It should be zero if we are
365 not doing a dynamic link, or the start of the .dynamic section if
367 if (! link_info.relocateable)
369 h->type = bfd_link_hash_defined;
372 h->u.def.section = sdyn;
374 h->u.def.section = bfd_abs_section_ptr;
378 /* This is called by the before_allocation routine via
379 lang_for_each_statement. It locates any assignment statements, and
380 tells the backend linker about them, in case they are assignments
381 to symbols which are referred to by dynamic objects. */
384 gld${EMULATION_NAME}_find_statement_assignment (s)
385 lang_statement_union_type *s;
387 if (s->header.type == lang_assignment_statement_enum)
388 gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
391 /* Look through an expression for an assignment statement. */
394 gld${EMULATION_NAME}_find_exp_assignment (exp)
397 switch (exp->type.node_class)
400 if (strcmp (exp->assign.dst, ".") != 0)
402 if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
404 einfo ("%P%F: failed to record assignment to %s: %E\n",
407 gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
411 gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
412 gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
416 gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
417 gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
418 gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
422 gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
430 /* Work out the size of the .need section, and the number of entries.
431 The backend will set the ld_need field of the dynamic linking
432 information to point to the .need section. See include/aout/sun4.h
433 for more information. */
436 gld${EMULATION_NAME}_count_need (inp)
437 lang_input_statement_type *inp;
439 if (inp->the_bfd != NULL
440 && (inp->the_bfd->flags & DYNAMIC) != 0)
443 need_size += NEED_ENTRY_SIZE;
444 if (! inp->is_archive)
445 need_size += strlen (inp->filename) + 1;
448 ASSERT (inp->local_sym_name[0] == '-'
449 && inp->local_sym_name[1] == 'l');
450 need_size += strlen (inp->local_sym_name + 2) + 1;
455 /* Fill in the contents of the .need section. */
458 gld${EMULATION_NAME}_set_need (inp)
459 lang_input_statement_type *inp;
461 if (inp->the_bfd != NULL
462 && (inp->the_bfd->flags & DYNAMIC) != 0)
466 /* To really fill in the .need section contents, we need to know
467 the final file position of the section, but we don't.
468 Instead, we use offsets, and rely on the BFD backend to
469 finish the section up correctly. FIXME: Talk about lack of
470 referential locality. */
471 bfd_put_32 (output_bfd, need_pnames - need_contents, need_pinfo);
472 if (! inp->is_archive)
474 bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 4);
475 bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 8);
476 bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 10);
477 strcpy (need_pnames, inp->filename);
484 bfd_put_32 (output_bfd, (bfd_vma) 0x80000000, need_pinfo + 4);
487 verstr = strstr (inp->filename, ".so.");
489 sscanf (verstr, ".so.%d.%d", &maj, &min);
490 bfd_put_16 (output_bfd, (bfd_vma) maj, need_pinfo + 8);
491 bfd_put_16 (output_bfd, (bfd_vma) min, need_pinfo + 10);
492 strcpy (need_pnames, inp->local_sym_name + 2);
495 c = (need_pinfo - need_contents) / NEED_ENTRY_SIZE;
496 if (c + 1 >= need_entries)
497 bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 12);
499 bfd_put_32 (output_bfd, (bfd_vma) (c + 1) * NEED_ENTRY_SIZE,
502 need_pinfo += NEED_ENTRY_SIZE;
503 need_pnames += strlen (need_pnames) + 1;
508 gld${EMULATION_NAME}_get_script(isfile)
512 if test -n "$COMPILE_IN"
514 # Scripts compiled in.
516 # sed commands to quote an ld script as a C string.
523 cat >>e${EMULATION_NAME}.c <<EOF
527 if (link_info.relocateable == true && config.build_constructors == true)
528 return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
529 else if (link_info.relocateable == true)
530 return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
531 else if (!config.text_read_only)
532 return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
533 else if (!config.magic_demand_paged)
534 return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
536 return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
541 # Scripts read from the filesystem.
543 cat >>e${EMULATION_NAME}.c <<EOF
547 if (link_info.relocateable == true && config.build_constructors == true)
548 return "ldscripts/${EMULATION_NAME}.xu";
549 else if (link_info.relocateable == true)
550 return "ldscripts/${EMULATION_NAME}.xr";
551 else if (!config.text_read_only)
552 return "ldscripts/${EMULATION_NAME}.xbn";
553 else if (!config.magic_demand_paged)
554 return "ldscripts/${EMULATION_NAME}.xn";
556 return "ldscripts/${EMULATION_NAME}.x";
562 cat >>e${EMULATION_NAME}.c <<EOF
564 struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
566 gld${EMULATION_NAME}_before_parse,
571 after_allocation_default,
572 set_output_arch_default,
573 ldemul_default_target,
574 gld${EMULATION_NAME}_before_allocation,
575 gld${EMULATION_NAME}_get_script,
579 gld${EMULATION_NAME}_create_output_section_statements,
580 NULL /* open_dynamic_library */