Correct handling of .sa file.
[external/binutils.git] / ld / emultempl / sunos.em
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! */
5
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>
10
11 This file is part of GLD, the Gnu Linker.
12
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.
17
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.
22
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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
26
27 #define TARGET_IS_${EMULATION_NAME}
28
29 #include <sys/types.h>
30 #include <sys/stat.h>
31
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.  */
36 #include <dirent.h>
37
38 #include "bfd.h"
39 #include "sysdep.h"
40 #include "bfdlink.h"
41
42 #include "ld.h"
43 #include "config.h"
44 #include "ldmain.h"
45 #include "ldemul.h"
46 #include "ldfile.h"
47 #include "ldmisc.h"
48 #include "ldexp.h"
49 #include "ldlang.h"
50
51 static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
52 static void gld${EMULATION_NAME}_create_output_section_statements
53   PARAMS ((void));
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));
65
66 static void
67 gld${EMULATION_NAME}_before_parse()
68 {
69   ldfile_output_architecture = bfd_arch_${ARCH};
70   config.dynamic_link = true;
71 }
72
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.  */
81
82 static void
83 gld${EMULATION_NAME}_create_output_section_statements ()
84 {
85   lang_for_each_input_file (gld${EMULATION_NAME}_find_so);
86 }
87
88 /* Search the directory for a .so file for each library search.  */
89
90 static void
91 gld${EMULATION_NAME}_find_so (inp)
92      lang_input_statement_type *inp;
93 {
94   search_dirs_type *search;
95   const char *filename;
96   const char *dot;
97   int force_maj;
98   unsigned int len;
99   char *alc;
100   int max_maj, max_min;
101   char *found;
102   struct stat st;
103
104   if (! inp->search_dirs_flag
105       || ! inp->is_archive)
106     return;
107
108   ASSERT (strncmp (inp->local_sym_name, "-l", 2) == 0);
109
110   filename = inp->filename;
111   force_maj = -1;
112   dot = strchr (filename, '.');
113   if (dot == NULL)
114     len = strlen (filename);
115   else
116     {
117       len = dot - filename;
118       alc = (char *) alloca (len + 1);
119       strncpy (alc, filename, len);
120       alc[len] = '\0';
121       filename = alc;
122     }
123
124   found = NULL;
125   max_maj = max_min = 0;
126   for (search = search_head; search != NULL; search = search->next)
127     {
128       DIR *dir;
129       struct dirent *entry;
130
131       dir = opendir (search->name);
132       if (dir == NULL)
133         continue;
134   
135       while ((entry = readdir (dir)) != NULL)
136         {
137           int found_maj, found_min;
138
139           if (strncmp (entry->d_name, "lib", 3) != 0
140               || strncmp (entry->d_name + 3, inp->filename, len) != 0
141               || strncmp (entry->d_name + 3 + len, ".so", 3) != 0)
142             continue;
143
144           /* We've found a .so file.  Work out the major and minor
145              version numbers.  */
146           found_maj = 0;
147           found_min = 0;
148           sscanf (entry->d_name + 3 + len, ".so.%d.%d",
149                   &found_maj, &found_min);
150
151           if (force_maj != -1 && force_maj != found_maj)
152             continue;
153
154           /* We've found a match for the name we are searching for.
155              See if this is the version we should use.  If the major
156              and minor versions match, we use the last entry in
157              alphabetical order; I don't know if this is how SunOS
158              distinguishes libc.so.1.8 from libc.so.1.8.1, but it
159              ought to suffice.  */
160           if (found == NULL
161               || (found_maj > max_maj)
162               || (found_maj == max_maj
163                   && (found_min > max_min
164                       || (found_min == max_min
165                           && strcmp (entry->d_name, found) > 0))))
166             {
167               if (found != NULL)
168                 free (found);
169               found = (char *) xmalloc (strlen (entry->d_name) + 1);
170               strcpy (found, entry->d_name);
171               max_maj = found_maj;
172               max_min = found_min;
173             }
174         }
175
176       closedir (dir);
177
178       if (found != NULL)
179         break;
180     }
181
182   if (found == NULL)
183     {
184       /* We did not find a matching .so file.  This isn't an error,
185          since there might still be a matching .a file, which will be
186          found by the usual search.  */
187       return;
188     }
189
190   /* Replace the filename with the one we have found.  */
191   alc = (char *) xmalloc (strlen (search->name) + strlen (found) + 2);
192   sprintf (alc, "%s/%s", search->name, found);
193   inp->filename = alc;
194
195   /* Turn off the search_dirs_flag to prevent ldfile_open_file from
196      searching for this file again.  */
197   inp->search_dirs_flag = false;
198
199   free (found);
200
201   /* Now look for the same file name, but with .sa instead of .so.  If
202      found, add it to the list of input files.  */
203   alc = (char *) alloca (strlen (inp->filename) + 1);
204   strcpy (alc, inp->filename);
205   strstr (alc, ".so.")[2] = 'a';
206   if (stat (alc, &st) == 0)
207     {
208       lang_input_statement_type *sa;
209       char *a;
210
211       /* Add the .sa file to the statement list just after the .so
212          file.  This is really a hack.  */
213       sa = ((lang_input_statement_type *)
214             xmalloc (sizeof (lang_input_statement_type)));
215       sa->header.next = inp->header.next;
216       sa->header.type = lang_input_statement_enum;
217       a = (char *) xmalloc (strlen (alc) + 1);
218       strcpy (a, alc);
219       sa->filename = a;
220       sa->local_sym_name = a;
221       sa->the_bfd = NULL;
222       sa->asymbols = NULL;
223       sa->symbol_count = 0;
224       sa->next = NULL;
225       sa->next_real_file = inp->next_real_file;
226       sa->is_archive = false;
227       sa->search_dirs_flag = false;
228       sa->just_syms_flag = false;
229       sa->loaded = false;
230       sa->real = true;
231       sa->complained = false;
232
233       /* Put the new statement next on the list of statements and next
234          on the list of input files.  */
235       inp->header.next = (lang_statement_union_type *) sa;
236       inp->next_real_file = (lang_statement_union_type *) sa;
237     }
238 }
239
240 /* We need to use static variables to pass information around the call
241    to lang_for_each_input_file.  Ick.  */
242
243 static bfd_size_type need_size;
244 static bfd_size_type need_entries;
245 static bfd_byte *need_contents;
246 static bfd_byte *need_pinfo;
247 static bfd_byte *need_pnames;
248
249 /* The size of one entry in the .need section, not including the file
250    name.  */
251
252 #define NEED_ENTRY_SIZE (16)
253
254 /* This is called after the sections have been attached to output
255    sections, but before any sizes or addresses have been set.  */
256
257 static void
258 gld${EMULATION_NAME}_before_allocation ()
259 {
260   struct bfd_link_hash_entry *h = NULL;
261   asection *sneed;
262   asection *srules;
263   asection *sdyn;
264
265   /* We need to create a __DYNAMIC symbol.  We don't do this in the
266      linker script because we want to set the value to the start of
267      the dynamic section if there is one, or to zero if there isn't
268      one.  We need to create the symbol before calling
269      size_dynamic_sections, although we can't set the value until
270      afterward.  */
271   if (! link_info.relocateable)
272     {
273       h = bfd_link_hash_lookup (link_info.hash, "__DYNAMIC", true, false,
274                                 false);
275       if (h == NULL)
276         einfo ("%P%F: bfd_link_hash_lookup: %E\n");
277       if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
278                                               "__DYNAMIC"))
279         einfo ("%P%F: failed to record assignment to __DYNAMIC: %E\n");
280     }
281
282   /* If we are going to make any variable assignments, we need to let
283      the backend linker know about them in case the variables are
284      referred to by dynamic objects.  */
285   lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
286
287   /* Let the backend linker work out the sizes of any sections
288      required by dynamic linking.  */
289   if (! bfd_sunos_size_dynamic_sections (output_bfd, &link_info, &sdyn,
290                                          &sneed, &srules))
291     einfo ("%P%F: failed to set dynamic section sizes: %E\n");
292
293   if (sneed != NULL)
294     {
295       /* Set up the .need section.  See the description of the ld_need
296          field in include/sun4/aout.h.  */
297
298       need_entries = 0;
299       need_size = 0;
300
301       lang_for_each_input_file (gld${EMULATION_NAME}_count_need);
302
303       /* We should only have a .need section if we have at least one
304          dynamic object.  */
305       ASSERT (need_entries != 0);
306
307       sneed->_raw_size = need_size;
308       sneed->contents = (bfd_byte *) xmalloc (need_size);
309
310       need_contents = sneed->contents;
311       need_pinfo = sneed->contents;
312       need_pnames = sneed->contents + need_entries * 16;
313
314       lang_for_each_input_file (gld${EMULATION_NAME}_set_need);
315
316       ASSERT (need_pnames - sneed->contents == need_size);
317     }
318
319   if (srules != NULL)
320     {
321       unsigned int size;
322       search_dirs_type *search;
323
324       /* Set up the .rules section.  This is just a PATH like string
325          of the -L arguments given on the command line.  */
326       size = 0;
327       for (search = search_head; search != NULL; search = search->next)
328         if (search->cmdline)
329           size += strlen (search->name) + 1;
330       srules->_raw_size = size;
331       if (size > 0)
332         {
333           char *p;
334
335           srules->contents = (bfd_byte *) xmalloc (size);
336           p = (char *) srules->contents;
337           *p = '\0';
338           for (search = search_head; search != NULL; search = search->next)
339             {
340               if (search->cmdline)
341                 {
342                   if (p != (char *) srules->contents)
343                     *p++ = ':';
344                   strcpy (p, search->name);
345                   p += strlen (p);
346                 }
347             }
348         }
349     }
350
351   /* We must assign a value to __DYNAMIC.  It should be zero if we are
352      not doing a dynamic link, or the start of the .dynamic section if
353      we are doing one.  */
354   if (! link_info.relocateable)
355     {
356       h->type = bfd_link_hash_defined;
357       h->u.def.value = 0;
358       if (sdyn != NULL)
359         h->u.def.section = sdyn;
360       else
361         h->u.def.section = &bfd_abs_section;
362     }
363 }
364
365 /* This is called by the before_allocation routine via
366    lang_for_each_statement.  It locates any assignment statements, and
367    tells the backend linker about them, in case they are assignments
368    to symbols which are referred to by dynamic objects.  */
369
370 static void
371 gld${EMULATION_NAME}_find_statement_assignment (s)
372      lang_statement_union_type *s;
373 {
374   if (s->header.type == lang_assignment_statement_enum)
375     gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
376 }
377
378 /* Look through an expression for an assignment statement.  */
379
380 static void
381 gld${EMULATION_NAME}_find_exp_assignment (exp)
382      etree_type *exp;
383 {
384   switch (exp->type.node_class)
385     {
386     case etree_assign:
387       if (strcmp (exp->assign.dst, ".") != 0)
388         {
389           if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
390                                                   exp->assign.dst))
391             einfo ("%P%F: failed to record assignment to %s: %E\n",
392                    exp->assign.dst);
393         }
394       gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
395       break;
396
397     case etree_binary:
398       gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
399       gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
400       break;
401
402     case etree_trinary:
403       gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
404       gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
405       gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
406       break;
407
408     case etree_unary:
409       gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
410       break;
411
412     default:
413       break;
414     }
415 }
416
417 /* Work out the size of the .need section, and the number of entries.
418    The backend will set the ld_need field of the dynamic linking
419    information to point to the .need section.  See include/aout/sun4.h
420    for more information.  */
421
422 static void
423 gld${EMULATION_NAME}_count_need (inp)
424      lang_input_statement_type *inp;
425 {
426   if (inp->the_bfd != NULL
427       && (inp->the_bfd->flags & DYNAMIC) != 0)
428     {
429       ++need_entries;
430       need_size += NEED_ENTRY_SIZE;
431       if (! inp->is_archive)
432         need_size += strlen (inp->filename) + 1;
433       else
434         {
435           ASSERT (inp->local_sym_name[0] == '-'
436                   && inp->local_sym_name[1] == 'l');
437           need_size += strlen (inp->local_sym_name + 2) + 1;
438         }
439     }
440 }
441
442 /* Fill in the contents of the .need section.  */
443
444 static void
445 gld${EMULATION_NAME}_set_need (inp)
446      lang_input_statement_type *inp;
447 {
448   if (inp->the_bfd != NULL
449       && (inp->the_bfd->flags & DYNAMIC) != 0)
450     {
451       bfd_size_type c;
452
453       /* To really fill in the .need section contents, we need to know
454          the final file position of the section, but we don't.
455          Instead, we use offsets, and rely on the BFD backend to
456          finish the section up correctly.  FIXME: Talk about lack of
457          referential locality.  */
458       bfd_put_32 (output_bfd, need_pnames - need_contents, need_pinfo);
459       if (! inp->is_archive)
460         {
461           bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 4);
462           bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 8);
463           bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 10);
464           strcpy (need_pnames, inp->filename);
465         }
466       else
467         {
468           char *verstr;
469           int maj, min;
470
471           bfd_put_32 (output_bfd, (bfd_vma) 0x80000000, need_pinfo + 4);
472           maj = 0;
473           min = 0;
474           verstr = strstr (inp->filename, ".so.");
475           if (verstr != NULL)
476             sscanf (verstr, ".so.%d.%d", &maj, &min);
477           bfd_put_16 (output_bfd, (bfd_vma) maj, need_pinfo + 8);
478           bfd_put_16 (output_bfd, (bfd_vma) min, need_pinfo + 10);
479           strcpy (need_pnames, inp->local_sym_name + 2);
480         }
481
482       c = (need_pinfo - need_contents) / NEED_ENTRY_SIZE;
483       if (c + 1 >= need_entries)
484         bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 12);
485       else
486         bfd_put_32 (output_bfd, (bfd_vma) (c + 1) * NEED_ENTRY_SIZE,
487                     need_pinfo + 12);
488
489       need_pinfo += NEED_ENTRY_SIZE;
490       need_pnames += strlen (need_pnames) + 1;
491     }
492 }
493
494 static char *
495 gld${EMULATION_NAME}_get_script(isfile)
496      int *isfile;
497 EOF
498
499 if test -n "$COMPILE_IN"
500 then
501 # Scripts compiled in.
502
503 # sed commands to quote an ld script as a C string.
504 sc='s/["\\]/\\&/g
505 s/$/\\n\\/
506 1s/^/"/
507 $s/$/n"/
508 '
509
510 cat >>e${EMULATION_NAME}.c <<EOF
511 {                            
512   *isfile = 0;
513
514   if (link_info.relocateable == true && config.build_constructors == true)
515     return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
516   else if (link_info.relocateable == true)
517     return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
518   else if (!config.text_read_only)
519     return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
520   else if (!config.magic_demand_paged)
521     return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
522   else
523     return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
524 }
525 EOF
526
527 else
528 # Scripts read from the filesystem.
529
530 cat >>e${EMULATION_NAME}.c <<EOF
531 {                            
532   *isfile = 1;
533
534   if (link_info.relocateable == true && config.build_constructors == true)
535     return "ldscripts/${EMULATION_NAME}.xu";
536   else if (link_info.relocateable == true)
537     return "ldscripts/${EMULATION_NAME}.xr";
538   else if (!config.text_read_only)
539     return "ldscripts/${EMULATION_NAME}.xbn";
540   else if (!config.magic_demand_paged)
541     return "ldscripts/${EMULATION_NAME}.xn";
542   else
543     return "ldscripts/${EMULATION_NAME}.x";
544 }
545 EOF
546
547 fi
548
549 cat >>e${EMULATION_NAME}.c <<EOF
550
551 struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = 
552 {
553   gld${EMULATION_NAME}_before_parse,
554   syslib_default,
555   hll_default,
556   after_parse_default,
557   after_allocation_default,
558   set_output_arch_default,
559   ldemul_default_target,
560   gld${EMULATION_NAME}_before_allocation,
561   gld${EMULATION_NAME}_get_script,
562   "${EMULATION_NAME}",
563   "${OUTPUT_FORMAT}",
564   0, /* finish */
565   gld${EMULATION_NAME}_create_output_section_statements
566 };
567 EOF