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>
47 # define dirent direct
48 # ifdef HAVE_SYS_NDIR_H
49 # include <sys/ndir.h>
51 # ifdef HAVE_SYS_DIR_H
59 static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
60 static void gld${EMULATION_NAME}_create_output_section_statements
62 static void gld${EMULATION_NAME}_find_so
63 PARAMS ((lang_input_statement_type *));
64 static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
65 static void gld${EMULATION_NAME}_find_statement_assignment
66 PARAMS ((lang_statement_union_type *));
67 static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
68 static void gld${EMULATION_NAME}_count_need
69 PARAMS ((lang_input_statement_type *));
70 static void gld${EMULATION_NAME}_set_need
71 PARAMS ((lang_input_statement_type *));
72 static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
75 gld${EMULATION_NAME}_before_parse()
77 ldfile_output_architecture = bfd_arch_${ARCH};
78 config.dynamic_link = true;
81 /* Despite the name, we use this routine to search for dynamic
82 libraries. On SunOS this requires a directory search. We need to
83 find the .so file with the highest version number. The user may
84 restrict the major version by saying, e.g., -lc.1. Also, if we
85 find a .so file, we need to look for a the same file after
86 replacing .so with .sa; if it exists, it will be an archive which
87 provide some initializations for data symbols, and we need to
88 search it after including the .so file. */
91 gld${EMULATION_NAME}_create_output_section_statements ()
93 lang_for_each_input_file (gld${EMULATION_NAME}_find_so);
96 /* Search the directory for a .so file for each library search. */
99 gld${EMULATION_NAME}_find_so (inp)
100 lang_input_statement_type *inp;
102 search_dirs_type *search;
103 const char *filename;
108 int max_maj, max_min;
110 boolean found_static;
113 if (! inp->search_dirs_flag
118 ASSERT (strncmp (inp->local_sym_name, "-l", 2) == 0);
120 filename = inp->filename;
122 dot = strchr (filename, '.');
124 len = strlen (filename);
127 force_maj = atoi (dot + 1);
128 len = dot - filename;
129 alc = (char *) xmalloc (len + 1);
130 strncpy (alc, filename, len);
136 found_static = false;
137 max_maj = max_min = 0;
138 for (search = search_head; search != NULL; search = search->next)
141 struct dirent *entry;
143 dir = opendir (search->name);
147 while ((entry = readdir (dir)) != NULL)
149 int found_maj, found_min;
151 if (strncmp (entry->d_name, "lib", 3) != 0
152 || strncmp (entry->d_name + 3, inp->filename, len) != 0)
156 && strncmp (entry->d_name + 3 + len, ".a", 2) == 0)
162 if (strncmp (entry->d_name + 3 + len, ".so", 3) != 0)
165 /* We've found a .so file. Work out the major and minor
169 sscanf (entry->d_name + 3 + len, ".so.%d.%d",
170 &found_maj, &found_min);
172 if (force_maj != -1 && force_maj != found_maj)
175 /* We've found a match for the name we are searching for.
176 See if this is the version we should use. If the major
177 and minor versions match, we use the last entry in
178 alphabetical order; I don't know if this is how SunOS
179 distinguishes libc.so.1.8 from libc.so.1.8.1, but it
182 || (found_maj > max_maj)
183 || (found_maj == max_maj
184 && (found_min > max_min
185 || (found_min == max_min
186 && strcmp (entry->d_name, found) > 0))))
190 found = (char *) xmalloc (strlen (entry->d_name) + 1);
191 strcpy (found, entry->d_name);
199 if (found != NULL || found_static)
205 /* We did not find a matching .so file. This isn't an error,
206 since there might still be a matching .a file, which will be
207 found by the usual search. */
211 /* Replace the filename with the one we have found. */
212 alc = (char *) xmalloc (strlen (search->name) + strlen (found) + 2);
213 sprintf (alc, "%s/%s", search->name, found);
216 /* Turn off the search_dirs_flag to prevent ldfile_open_file from
217 searching for this file again. */
218 inp->search_dirs_flag = false;
222 /* Now look for the same file name, but with .sa instead of .so. If
223 found, add it to the list of input files. */
224 alc = (char *) xmalloc (strlen (inp->filename) + 1);
225 strcpy (alc, inp->filename);
226 strstr (alc, ".so.")[2] = 'a';
227 if (stat (alc, &st) == 0)
229 lang_input_statement_type *sa;
232 /* Add the .sa file to the statement list just after the .so
233 file. This is really a hack. */
234 sa = ((lang_input_statement_type *)
235 xmalloc (sizeof (lang_input_statement_type)));
236 sa->header.next = inp->header.next;
237 sa->header.type = lang_input_statement_enum;
238 a = (char *) xmalloc (strlen (alc) + 1);
241 sa->local_sym_name = a;
244 sa->symbol_count = 0;
246 sa->next_real_file = inp->next_real_file;
247 sa->is_archive = false;
248 sa->search_dirs_flag = false;
249 sa->just_syms_flag = false;
252 sa->complained = false;
254 /* Put the new statement next on the list of statements and next
255 on the list of input files. */
256 inp->header.next = (lang_statement_union_type *) sa;
257 inp->next_real_file = (lang_statement_union_type *) sa;
261 /* We need to use static variables to pass information around the call
262 to lang_for_each_input_file. Ick. */
264 static bfd_size_type need_size;
265 static bfd_size_type need_entries;
266 static bfd_byte *need_contents;
267 static bfd_byte *need_pinfo;
268 static bfd_byte *need_pnames;
270 /* The size of one entry in the .need section, not including the file
273 #define NEED_ENTRY_SIZE (16)
275 /* This is called after the sections have been attached to output
276 sections, but before any sizes or addresses have been set. */
279 gld${EMULATION_NAME}_before_allocation ()
281 struct bfd_link_hash_entry *h = NULL;
286 /* We need to create a __DYNAMIC symbol. We don't do this in the
287 linker script because we want to set the value to the start of
288 the dynamic section if there is one, or to zero if there isn't
289 one. We need to create the symbol before calling
290 size_dynamic_sections, although we can't set the value until
292 if (! link_info.relocateable)
294 h = bfd_link_hash_lookup (link_info.hash, "__DYNAMIC", true, false,
297 einfo ("%P%F: bfd_link_hash_lookup: %E\n");
298 if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
300 einfo ("%P%F: failed to record assignment to __DYNAMIC: %E\n");
303 /* If we are going to make any variable assignments, we need to let
304 the backend linker know about them in case the variables are
305 referred to by dynamic objects. */
306 lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
308 /* Let the backend linker work out the sizes of any sections
309 required by dynamic linking. */
310 if (! bfd_sunos_size_dynamic_sections (output_bfd, &link_info, &sdyn,
312 einfo ("%P%F: failed to set dynamic section sizes: %E\n");
316 /* Set up the .need section. See the description of the ld_need
317 field in include/aout/sun4.h. */
322 lang_for_each_input_file (gld${EMULATION_NAME}_count_need);
324 /* We should only have a .need section if we have at least one
326 ASSERT (need_entries != 0);
328 sneed->_raw_size = need_size;
329 sneed->contents = (bfd_byte *) xmalloc (need_size);
331 need_contents = sneed->contents;
332 need_pinfo = sneed->contents;
333 need_pnames = sneed->contents + need_entries * 16;
335 lang_for_each_input_file (gld${EMULATION_NAME}_set_need);
337 ASSERT ((bfd_size_type) (need_pnames - sneed->contents) == need_size);
343 search_dirs_type *search;
345 /* Set up the .rules section. This is just a PATH like string
346 of the -L arguments given on the command line. */
348 for (search = search_head; search != NULL; search = search->next)
350 size += strlen (search->name) + 1;
351 srules->_raw_size = size;
356 srules->contents = (bfd_byte *) xmalloc (size);
357 p = (char *) srules->contents;
359 for (search = search_head; search != NULL; search = search->next)
363 if (p != (char *) srules->contents)
365 strcpy (p, search->name);
372 /* We must assign a value to __DYNAMIC. It should be zero if we are
373 not doing a dynamic link, or the start of the .dynamic section if
375 if (! link_info.relocateable)
377 h->type = bfd_link_hash_defined;
380 h->u.def.section = sdyn;
382 h->u.def.section = bfd_abs_section_ptr;
386 /* This is called by the before_allocation routine via
387 lang_for_each_statement. It locates any assignment statements, and
388 tells the backend linker about them, in case they are assignments
389 to symbols which are referred to by dynamic objects. */
392 gld${EMULATION_NAME}_find_statement_assignment (s)
393 lang_statement_union_type *s;
395 if (s->header.type == lang_assignment_statement_enum)
396 gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
399 /* Look through an expression for an assignment statement. */
402 gld${EMULATION_NAME}_find_exp_assignment (exp)
405 switch (exp->type.node_class)
408 if (strcmp (exp->assign.dst, ".") != 0)
410 if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
412 einfo ("%P%F: failed to record assignment to %s: %E\n",
415 gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
419 gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
420 gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
424 gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
425 gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
426 gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
430 gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
438 /* Work out the size of the .need section, and the number of entries.
439 The backend will set the ld_need field of the dynamic linking
440 information to point to the .need section. See include/aout/sun4.h
441 for more information. */
444 gld${EMULATION_NAME}_count_need (inp)
445 lang_input_statement_type *inp;
447 if (inp->the_bfd != NULL
448 && (inp->the_bfd->flags & DYNAMIC) != 0)
451 need_size += NEED_ENTRY_SIZE;
452 if (! inp->is_archive)
453 need_size += strlen (inp->filename) + 1;
456 ASSERT (inp->local_sym_name[0] == '-'
457 && inp->local_sym_name[1] == 'l');
458 need_size += strlen (inp->local_sym_name + 2) + 1;
463 /* Fill in the contents of the .need section. */
466 gld${EMULATION_NAME}_set_need (inp)
467 lang_input_statement_type *inp;
469 if (inp->the_bfd != NULL
470 && (inp->the_bfd->flags & DYNAMIC) != 0)
474 /* To really fill in the .need section contents, we need to know
475 the final file position of the section, but we don't.
476 Instead, we use offsets, and rely on the BFD backend to
477 finish the section up correctly. FIXME: Talk about lack of
478 referential locality. */
479 bfd_put_32 (output_bfd, need_pnames - need_contents, need_pinfo);
480 if (! inp->is_archive)
482 bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 4);
483 bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 8);
484 bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 10);
485 strcpy (need_pnames, inp->filename);
492 bfd_put_32 (output_bfd, (bfd_vma) 0x80000000, need_pinfo + 4);
495 verstr = strstr (inp->filename, ".so.");
497 sscanf (verstr, ".so.%d.%d", &maj, &min);
498 bfd_put_16 (output_bfd, (bfd_vma) maj, need_pinfo + 8);
499 bfd_put_16 (output_bfd, (bfd_vma) min, need_pinfo + 10);
500 strcpy (need_pnames, inp->local_sym_name + 2);
503 c = (need_pinfo - need_contents) / NEED_ENTRY_SIZE;
504 if (c + 1 >= need_entries)
505 bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 12);
507 bfd_put_32 (output_bfd, (bfd_vma) (c + 1) * NEED_ENTRY_SIZE,
510 need_pinfo += NEED_ENTRY_SIZE;
511 need_pnames += strlen (need_pnames) + 1;
516 gld${EMULATION_NAME}_get_script(isfile)
520 if test -n "$COMPILE_IN"
522 # Scripts compiled in.
524 # sed commands to quote an ld script as a C string.
531 cat >>e${EMULATION_NAME}.c <<EOF
535 if (link_info.relocateable == true && config.build_constructors == true)
536 return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
537 else if (link_info.relocateable == true)
538 return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
539 else if (!config.text_read_only)
540 return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
541 else if (!config.magic_demand_paged)
542 return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
543 else if (link_info.shared)
544 return `sed "$sc" ldscripts/${EMULATION_NAME}.xs`;
546 return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
551 # Scripts read from the filesystem.
553 cat >>e${EMULATION_NAME}.c <<EOF
557 if (link_info.relocateable == true && config.build_constructors == true)
558 return "ldscripts/${EMULATION_NAME}.xu";
559 else if (link_info.relocateable == true)
560 return "ldscripts/${EMULATION_NAME}.xr";
561 else if (!config.text_read_only)
562 return "ldscripts/${EMULATION_NAME}.xbn";
563 else if (!config.magic_demand_paged)
564 return "ldscripts/${EMULATION_NAME}.xn";
565 else if (link_info.shared)
566 return "ldscripts/${EMULATION_NAME}.xs";
568 return "ldscripts/${EMULATION_NAME}.x";
574 cat >>e${EMULATION_NAME}.c <<EOF
576 struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
578 gld${EMULATION_NAME}_before_parse,
583 after_allocation_default,
584 set_output_arch_default,
585 ldemul_default_target,
586 gld${EMULATION_NAME}_before_allocation,
587 gld${EMULATION_NAME}_get_script,
591 gld${EMULATION_NAME}_create_output_section_statements,
592 NULL /* open_dynamic_library */