* configure.in: Call AC_HEADER_DIRENT.
[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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
26
27 #define TARGET_IS_${EMULATION_NAME}
28
29 #include <sys/types.h>
30 #include <sys/stat.h>
31
32 #include "bfd.h"
33 #include "sysdep.h"
34 #include "bfdlink.h"
35
36 #include "ld.h"
37 #include "ldmain.h"
38 #include "ldemul.h"
39 #include "ldfile.h"
40 #include "ldmisc.h"
41 #include "ldexp.h"
42 #include "ldlang.h"
43
44 #ifdef HAVE_DIRENT_H
45 # include <dirent.h>
46 #else
47 # define dirent direct
48 # ifdef HAVE_SYS_NDIR_H
49 #  include <sys/ndir.h>
50 # endif
51 # ifdef HAVE_SYS_DIR_H
52 #  include <sys/dir.h>
53 # endif
54 # ifdef HAVE_NDIR_H
55 #  include <ndir.h>
56 # endif
57 #endif
58
59 static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
60 static void gld${EMULATION_NAME}_create_output_section_statements
61   PARAMS ((void));
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));
73
74 static void
75 gld${EMULATION_NAME}_before_parse()
76 {
77   ldfile_output_architecture = bfd_arch_${ARCH};
78   config.dynamic_link = true;
79 }
80
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.  */
89
90 static void
91 gld${EMULATION_NAME}_create_output_section_statements ()
92 {
93   lang_for_each_input_file (gld${EMULATION_NAME}_find_so);
94 }
95
96 /* Search the directory for a .so file for each library search.  */
97
98 static void
99 gld${EMULATION_NAME}_find_so (inp)
100      lang_input_statement_type *inp;
101 {
102   search_dirs_type *search;
103   const char *filename;
104   const char *dot;
105   int force_maj;
106   unsigned int len;
107   char *alc;
108   int max_maj, max_min;
109   char *found;
110   boolean found_static;
111   struct stat st;
112
113   if (! inp->search_dirs_flag
114       || ! inp->is_archive
115       || ! inp->dynamic)
116     return;
117
118   ASSERT (strncmp (inp->local_sym_name, "-l", 2) == 0);
119
120   filename = inp->filename;
121   force_maj = -1;
122   dot = strchr (filename, '.');
123   if (dot == NULL)
124     len = strlen (filename);
125   else
126     {
127       force_maj = atoi (dot + 1);
128       len = dot - filename;
129       alc = (char *) xmalloc (len + 1);
130       strncpy (alc, filename, len);
131       alc[len] = '\0';
132       filename = alc;
133     }
134
135   found = NULL;
136   found_static = false;
137   max_maj = max_min = 0;
138   for (search = search_head; search != NULL; search = search->next)
139     {
140       DIR *dir;
141       struct dirent *entry;
142
143       dir = opendir (search->name);
144       if (dir == NULL)
145         continue;
146   
147       while ((entry = readdir (dir)) != NULL)
148         {
149           int found_maj, found_min;
150
151           if (strncmp (entry->d_name, "lib", 3) != 0
152               || strncmp (entry->d_name + 3, inp->filename, len) != 0)
153             continue;
154
155           if (dot == NULL
156               && strncmp (entry->d_name + 3 + len, ".a", 2) == 0)
157             {
158               found_static = true;
159               continue;
160             }
161
162           if (strncmp (entry->d_name + 3 + len, ".so", 3) != 0)
163             continue;
164
165           /* We've found a .so file.  Work out the major and minor
166              version numbers.  */
167           found_maj = 0;
168           found_min = 0;
169           sscanf (entry->d_name + 3 + len, ".so.%d.%d",
170                   &found_maj, &found_min);
171
172           if (force_maj != -1 && force_maj != found_maj)
173             continue;
174
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
180              ought to suffice.  */
181           if (found == NULL
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))))
187             {
188               if (found != NULL)
189                 free (found);
190               found = (char *) xmalloc (strlen (entry->d_name) + 1);
191               strcpy (found, entry->d_name);
192               max_maj = found_maj;
193               max_min = found_min;
194             }
195         }
196
197       closedir (dir);
198
199       if (found != NULL || found_static)
200         break;
201     }
202
203   if (found == NULL)
204     {
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.  */
208       return;
209     }
210
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);
214   inp->filename = alc;
215
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;
219
220   free (found);
221
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)
228     {
229       lang_input_statement_type *sa;
230       char *a;
231
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);
239       strcpy (a, alc);
240       sa->filename = a;
241       sa->local_sym_name = a;
242       sa->the_bfd = NULL;
243       sa->asymbols = NULL;
244       sa->symbol_count = 0;
245       sa->next = NULL;
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;
250       sa->loaded = false;
251       sa->real = true;
252       sa->complained = false;
253
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;
258     }
259 }
260
261 /* We need to use static variables to pass information around the call
262    to lang_for_each_input_file.  Ick.  */
263
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;
269
270 /* The size of one entry in the .need section, not including the file
271    name.  */
272
273 #define NEED_ENTRY_SIZE (16)
274
275 /* This is called after the sections have been attached to output
276    sections, but before any sizes or addresses have been set.  */
277
278 static void
279 gld${EMULATION_NAME}_before_allocation ()
280 {
281   struct bfd_link_hash_entry *h = NULL;
282   asection *sneed;
283   asection *srules;
284   asection *sdyn;
285
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
291      afterward.  */
292   if (! link_info.relocateable)
293     {
294       h = bfd_link_hash_lookup (link_info.hash, "__DYNAMIC", true, false,
295                                 false);
296       if (h == NULL)
297         einfo ("%P%F: bfd_link_hash_lookup: %E\n");
298       if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
299                                               "__DYNAMIC"))
300         einfo ("%P%F: failed to record assignment to __DYNAMIC: %E\n");
301     }
302
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);
307
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,
311                                          &sneed, &srules))
312     einfo ("%P%F: failed to set dynamic section sizes: %E\n");
313
314   if (sneed != NULL)
315     {
316       /* Set up the .need section.  See the description of the ld_need
317          field in include/aout/sun4.h.  */
318
319       need_entries = 0;
320       need_size = 0;
321
322       lang_for_each_input_file (gld${EMULATION_NAME}_count_need);
323
324       /* We should only have a .need section if we have at least one
325          dynamic object.  */
326       ASSERT (need_entries != 0);
327
328       sneed->_raw_size = need_size;
329       sneed->contents = (bfd_byte *) xmalloc (need_size);
330
331       need_contents = sneed->contents;
332       need_pinfo = sneed->contents;
333       need_pnames = sneed->contents + need_entries * 16;
334
335       lang_for_each_input_file (gld${EMULATION_NAME}_set_need);
336
337       ASSERT (need_pnames - sneed->contents == need_size);
338     }
339
340   if (srules != NULL)
341     {
342       unsigned int size;
343       search_dirs_type *search;
344
345       /* Set up the .rules section.  This is just a PATH like string
346          of the -L arguments given on the command line.  */
347       size = 0;
348       for (search = search_head; search != NULL; search = search->next)
349         if (search->cmdline)
350           size += strlen (search->name) + 1;
351       srules->_raw_size = size;
352       if (size > 0)
353         {
354           char *p;
355
356           srules->contents = (bfd_byte *) xmalloc (size);
357           p = (char *) srules->contents;
358           *p = '\0';
359           for (search = search_head; search != NULL; search = search->next)
360             {
361               if (search->cmdline)
362                 {
363                   if (p != (char *) srules->contents)
364                     *p++ = ':';
365                   strcpy (p, search->name);
366                   p += strlen (p);
367                 }
368             }
369         }
370     }
371
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
374      we are doing one.  */
375   if (! link_info.relocateable)
376     {
377       h->type = bfd_link_hash_defined;
378       h->u.def.value = 0;
379       if (sdyn != NULL)
380         h->u.def.section = sdyn;
381       else
382         h->u.def.section = bfd_abs_section_ptr;
383     }
384 }
385
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.  */
390
391 static void
392 gld${EMULATION_NAME}_find_statement_assignment (s)
393      lang_statement_union_type *s;
394 {
395   if (s->header.type == lang_assignment_statement_enum)
396     gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
397 }
398
399 /* Look through an expression for an assignment statement.  */
400
401 static void
402 gld${EMULATION_NAME}_find_exp_assignment (exp)
403      etree_type *exp;
404 {
405   switch (exp->type.node_class)
406     {
407     case etree_assign:
408       if (strcmp (exp->assign.dst, ".") != 0)
409         {
410           if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
411                                                   exp->assign.dst))
412             einfo ("%P%F: failed to record assignment to %s: %E\n",
413                    exp->assign.dst);
414         }
415       gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
416       break;
417
418     case etree_binary:
419       gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
420       gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
421       break;
422
423     case etree_trinary:
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);
427       break;
428
429     case etree_unary:
430       gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
431       break;
432
433     default:
434       break;
435     }
436 }
437
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.  */
442
443 static void
444 gld${EMULATION_NAME}_count_need (inp)
445      lang_input_statement_type *inp;
446 {
447   if (inp->the_bfd != NULL
448       && (inp->the_bfd->flags & DYNAMIC) != 0)
449     {
450       ++need_entries;
451       need_size += NEED_ENTRY_SIZE;
452       if (! inp->is_archive)
453         need_size += strlen (inp->filename) + 1;
454       else
455         {
456           ASSERT (inp->local_sym_name[0] == '-'
457                   && inp->local_sym_name[1] == 'l');
458           need_size += strlen (inp->local_sym_name + 2) + 1;
459         }
460     }
461 }
462
463 /* Fill in the contents of the .need section.  */
464
465 static void
466 gld${EMULATION_NAME}_set_need (inp)
467      lang_input_statement_type *inp;
468 {
469   if (inp->the_bfd != NULL
470       && (inp->the_bfd->flags & DYNAMIC) != 0)
471     {
472       bfd_size_type c;
473
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)
481         {
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);
486         }
487       else
488         {
489           char *verstr;
490           int maj, min;
491
492           bfd_put_32 (output_bfd, (bfd_vma) 0x80000000, need_pinfo + 4);
493           maj = 0;
494           min = 0;
495           verstr = strstr (inp->filename, ".so.");
496           if (verstr != NULL)
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);
501         }
502
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);
506       else
507         bfd_put_32 (output_bfd, (bfd_vma) (c + 1) * NEED_ENTRY_SIZE,
508                     need_pinfo + 12);
509
510       need_pinfo += NEED_ENTRY_SIZE;
511       need_pnames += strlen (need_pnames) + 1;
512     }
513 }
514
515 static char *
516 gld${EMULATION_NAME}_get_script(isfile)
517      int *isfile;
518 EOF
519
520 if test -n "$COMPILE_IN"
521 then
522 # Scripts compiled in.
523
524 # sed commands to quote an ld script as a C string.
525 sc='s/["\\]/\\&/g
526 s/$/\\n\\/
527 1s/^/"/
528 $s/$/n"/
529 '
530
531 cat >>e${EMULATION_NAME}.c <<EOF
532 {                            
533   *isfile = 0;
534
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
544     return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
545 }
546 EOF
547
548 else
549 # Scripts read from the filesystem.
550
551 cat >>e${EMULATION_NAME}.c <<EOF
552 {                            
553   *isfile = 1;
554
555   if (link_info.relocateable == true && config.build_constructors == true)
556     return "ldscripts/${EMULATION_NAME}.xu";
557   else if (link_info.relocateable == true)
558     return "ldscripts/${EMULATION_NAME}.xr";
559   else if (!config.text_read_only)
560     return "ldscripts/${EMULATION_NAME}.xbn";
561   else if (!config.magic_demand_paged)
562     return "ldscripts/${EMULATION_NAME}.xn";
563   else
564     return "ldscripts/${EMULATION_NAME}.x";
565 }
566 EOF
567
568 fi
569
570 cat >>e${EMULATION_NAME}.c <<EOF
571
572 struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = 
573 {
574   gld${EMULATION_NAME}_before_parse,
575   syslib_default,
576   hll_default,
577   after_parse_default,
578   after_open_default,
579   after_allocation_default,
580   set_output_arch_default,
581   ldemul_default_target,
582   gld${EMULATION_NAME}_before_allocation,
583   gld${EMULATION_NAME}_get_script,
584   "${EMULATION_NAME}",
585   "${OUTPUT_FORMAT}",
586   NULL, /* finish */
587   gld${EMULATION_NAME}_create_output_section_statements,
588   NULL /* open_dynamic_library */
589 };
590 EOF