Correct handling of .sa file.
[deliverable/binutils-gdb.git] / ld / emultempl / sunos.em
CommitLineData
ed601bea
ILT
1# This shell script emits a C file. -*- C -*-
2# It does some substitutions.
3cat >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
11This file is part of GLD, the Gnu Linker.
12
13This program is free software; you can redistribute it and/or modify
14it under the terms of the GNU General Public License as published by
15the Free Software Foundation; either version 2 of the License, or
16(at your option) any later version.
17
18This program is distributed in the hope that it will be useful,
19but WITHOUT ANY WARRANTY; without even the implied warranty of
20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21GNU General Public License for more details.
22
23You should have received a copy of the GNU General Public License
24along with this program; if not, write to the Free Software
25Foundation, 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
51static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
52static void gld${EMULATION_NAME}_create_output_section_statements
53 PARAMS ((void));
54static void gld${EMULATION_NAME}_find_so
55 PARAMS ((lang_input_statement_type *));
56static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
57static void gld${EMULATION_NAME}_find_statement_assignment
58 PARAMS ((lang_statement_union_type *));
59static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
60static void gld${EMULATION_NAME}_count_need
61 PARAMS ((lang_input_statement_type *));
62static void gld${EMULATION_NAME}_set_need
63 PARAMS ((lang_input_statement_type *));
64static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
65
66static void
67gld${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
82static void
83gld${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
90static void
91gld${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;
2f4b5b53 224 sa->next = NULL;
ed601bea
ILT
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;
2f4b5b53
ILT
230 sa->real = true;
231 sa->complained = false;
ed601bea 232
2f4b5b53
ILT
233 /* Put the new statement next on the list of statements and next
234 on the list of input files. */
ed601bea 235 inp->header.next = (lang_statement_union_type *) sa;
ed601bea
ILT
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
243static bfd_size_type need_size;
244static bfd_size_type need_entries;
245static bfd_byte *need_contents;
246static bfd_byte *need_pinfo;
247static 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
257static void
258gld${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
370static void
371gld${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
380static void
381gld${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
422static void
423gld${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
444static void
445gld${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
494static char *
495gld${EMULATION_NAME}_get_script(isfile)
496 int *isfile;
497EOF
498
499if test -n "$COMPILE_IN"
500then
501# Scripts compiled in.
502
503# sed commands to quote an ld script as a C string.
504sc='s/["\\]/\\&/g
505s/$/\\n\\/
5061s/^/"/
507$s/$/n"/
508'
509
510cat >>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}
525EOF
526
527else
528# Scripts read from the filesystem.
529
530cat >>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}
545EOF
546
547fi
548
549cat >>e${EMULATION_NAME}.c <<EOF
550
551struct 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};
567EOF
This page took 0.043246 seconds and 4 git commands to generate.