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