* nlmconv.c (main): Use bfd_get_flavour instead of struct member.
[deliverable/binutils-gdb.git] / binutils / nlmconv.c
1 /* nlmconv.c -- NLM conversion program
2 Copyright (C) 1993 Free Software Foundation, Inc.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /* Written by Ian Lance Taylor <ian@cygnus.com>.
21
22 This program can be used to convert any appropriate object file
23 into a NetWare Loadable Module (an NLM). It will accept a linker
24 specification file which is identical to that accepted by the
25 NetWare linker, NLMLINK, except that the INPUT command, normally
26 used to give a list of object files to link together, is not used.
27 This program will convert only a single object file. */
28
29 #include <ansidecl.h>
30 #include <stdio.h>
31 #include <time.h>
32 #include <ctype.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/file.h>
36 #include <assert.h>
37 #include <getopt.h>
38 #include <bfd.h>
39 #include "sysdep.h"
40 #include "bucomm.h"
41 /* Internal BFD NLM header. */
42 #include "libnlm.h"
43 #include "nlmconv.h"
44
45 /* Needed for Alpha support. */
46 #include "coff/sym.h"
47 #include "coff/ecoff.h"
48
49 /* If strerror is just a macro, we want to use the one from libiberty
50 since it will handle undefined values. */
51 #undef strerror
52 extern char *strerror ();
53
54 #ifndef localtime
55 extern struct tm *localtime ();
56 #endif
57
58 #ifndef getenv
59 extern char *getenv ();
60 #endif
61
62 #ifndef SEEK_SET
63 #define SEEK_SET 0
64 #endif
65
66 #ifndef R_OK
67 #define R_OK 4
68 #define W_OK 2
69 #define X_OK 1
70 #endif
71 \f
72 /* Global variables. */
73
74 /* The name used to invoke the program. */
75 char *program_name;
76
77 /* The version number. */
78 extern char *program_version;
79
80 /* Local variables. */
81
82 /* Whether to print out debugging information (currently just controls
83 whether it prints the linker command if there is one). */
84 static int debug;
85
86 /* The symbol table. */
87 static asymbol **symbols;
88
89 /* A temporary file name to be unlinked on exit. Actually, for most
90 errors, we leave it around. It's not clear whether that is helpful
91 or not. */
92 static char *unlink_on_exit;
93
94 /* The list of long options. */
95 static struct option long_options[] =
96 {
97 { "debug", no_argument, 0, 'd' },
98 { "header-file", required_argument, 0, 'T' },
99 { "help", no_argument, 0, 'h' },
100 { "input-target", required_argument, 0, 'I' },
101 { "input-format", required_argument, 0, 'I' }, /* Obsolete */
102 { "linker", required_argument, 0, 'l' },
103 { "output-target", required_argument, 0, 'O' },
104 { "output-format", required_argument, 0, 'O' }, /* Obsolete */
105 { "version", no_argument, 0, 'V' },
106 { NULL, no_argument, 0, 0 }
107 };
108
109 /* Local routines. */
110
111 static void show_help PARAMS ((void));
112 static void show_usage PARAMS ((FILE *, int));
113 static const char *select_output_format PARAMS ((enum bfd_architecture,
114 unsigned long, boolean));
115 static void setup_sections PARAMS ((bfd *, asection *, PTR));
116 static void copy_sections PARAMS ((bfd *, asection *, PTR));
117 static void mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
118 bfd_size_type *, char *,
119 bfd_size_type));
120 static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
121 bfd_size_type *, char *,
122 bfd_size_type));
123 static void alpha_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
124 bfd_size_type *, char *,
125 bfd_size_type));
126 static void default_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
127 bfd_size_type *, char *,
128 bfd_size_type));
129 static char *link_inputs PARAMS ((struct string_list *, char *));
130 static const char *choose_temp_base_try PARAMS ((const char *,
131 const char *));
132 static void choose_temp_base PARAMS ((void));
133 static int pexecute PARAMS ((char *, char *[]));
134 \f
135 /* The main routine. */
136
137 int
138 main (argc, argv)
139 int argc;
140 char **argv;
141 {
142 int opt;
143 char *input_file = NULL;
144 const char *input_format = NULL;
145 const char *output_format = NULL;
146 const char *header_file = NULL;
147 char *ld_arg = NULL;
148 Nlm_Internal_Fixed_Header fixed_hdr_struct;
149 Nlm_Internal_Variable_Header var_hdr_struct;
150 Nlm_Internal_Version_Header version_hdr_struct;
151 Nlm_Internal_Copyright_Header copyright_hdr_struct;
152 Nlm_Internal_Extended_Header extended_hdr_struct;
153 bfd *inbfd;
154 bfd *outbfd;
155 asymbol **newsyms, **outsyms;
156 unsigned int symcount, newsymalloc, newsymcount;
157 asection *bss_sec, *data_sec;
158 bfd_vma vma;
159 bfd_size_type align;
160 asymbol *endsym;
161 unsigned int i;
162 char inlead, outlead;
163 boolean gotstart, gotexit, gotcheck;
164 struct stat st;
165 FILE *custom_data, *help_data, *message_data, *rpc_data, *shared_data;
166 size_t custom_size, help_size, message_size, module_size, rpc_size;
167 asection *custom_section, *help_section, *message_section, *module_section;
168 asection *rpc_section, *shared_section;
169 bfd *sharedbfd;
170 size_t shared_offset, shared_size;
171 Nlm_Internal_Fixed_Header sharedhdr;
172 int len;
173 char *modname;
174 char **matching;
175
176 program_name = argv[0];
177
178 bfd_init ();
179
180 while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options,
181 (int *) NULL))
182 != EOF)
183 {
184 switch (opt)
185 {
186 case 'd':
187 debug = 1;
188 break;
189 case 'h':
190 show_help ();
191 /*NOTREACHED*/
192 case 'I':
193 input_format = optarg;
194 break;
195 case 'l':
196 ld_arg = optarg;
197 break;
198 case 'O':
199 output_format = optarg;
200 break;
201 case 'T':
202 header_file = optarg;
203 break;
204 case 'V':
205 printf ("GNU %s version %s\n", program_name, program_version);
206 exit (0);
207 /*NOTREACHED*/
208 case 0:
209 break;
210 default:
211 show_usage (stderr, 1);
212 /*NOTREACHED*/
213 }
214 }
215
216 /* The input and output files may be named on the command line. */
217 output_file = NULL;
218 if (optind < argc)
219 {
220 input_file = argv[optind];
221 ++optind;
222 if (optind < argc)
223 {
224 output_file = argv[optind];
225 ++optind;
226 if (optind < argc)
227 show_usage (stderr, 1);
228 if (strcmp (input_file, output_file) == 0)
229 {
230 fprintf (stderr,
231 "%s: input and output files must be different\n",
232 program_name);
233 exit (1);
234 }
235 }
236 }
237
238 /* Initialize the header information to default values. */
239 fixed_hdr = &fixed_hdr_struct;
240 memset ((PTR) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct);
241 var_hdr = &var_hdr_struct;
242 memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct);
243 version_hdr = &version_hdr_struct;
244 memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct);
245 copyright_hdr = &copyright_hdr_struct;
246 memset ((PTR) &copyright_hdr_struct, 0, sizeof copyright_hdr_struct);
247 extended_hdr = &extended_hdr_struct;
248 memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct);
249 check_procedure = NULL;
250 custom_file = NULL;
251 debug_info = false;
252 exit_procedure = "_Stop";
253 export_symbols = NULL;
254 map_file = NULL;
255 full_map = false;
256 help_file = NULL;
257 import_symbols = NULL;
258 message_file = NULL;
259 modules = NULL;
260 sharelib_file = NULL;
261 start_procedure = "_Prelude";
262 verbose = false;
263 rpc_file = NULL;
264
265 parse_errors = 0;
266
267 /* Parse the header file (if there is one). */
268 if (header_file != NULL)
269 {
270 if (! nlmlex_file (header_file)
271 || yyparse () != 0
272 || parse_errors != 0)
273 exit (1);
274 }
275
276 if (input_files != NULL)
277 {
278 if (input_file != NULL)
279 {
280 fprintf (stderr,
281 "%s: input file named both on command line and with INPUT\n",
282 program_name);
283 exit (1);
284 }
285 if (input_files->next == NULL)
286 input_file = input_files->string;
287 else
288 input_file = link_inputs (input_files, ld_arg);
289 }
290 else if (input_file == NULL)
291 {
292 fprintf (stderr, "%s: no input file\n", program_name);
293 show_usage (stderr, 1);
294 }
295
296 inbfd = bfd_openr (input_file, input_format);
297 if (inbfd == NULL)
298 bfd_fatal (input_file);
299
300 if (! bfd_check_format_matches (inbfd, bfd_object, &matching))
301 {
302 bfd_nonfatal (input_file);
303 if (bfd_error == file_ambiguously_recognized)
304 {
305 list_matching_formats (matching);
306 free (matching);
307 }
308 exit (1);
309 }
310
311 if (output_format == NULL)
312 output_format = select_output_format (bfd_get_arch (inbfd),
313 bfd_get_mach (inbfd),
314 inbfd->xvec->byteorder_big_p);
315
316 assert (output_format != NULL);
317
318 /* Use the output file named on the command line if it exists.
319 Otherwise use the file named in the OUTPUT statement. */
320 if (output_file == NULL)
321 {
322 fprintf (stderr, "%s: no name for output file\n",
323 program_name);
324 show_usage (stderr, 1);
325 }
326
327 outbfd = bfd_openw (output_file, output_format);
328 if (outbfd == NULL)
329 bfd_fatal (output_file);
330 if (! bfd_set_format (outbfd, bfd_object))
331 bfd_fatal (output_file);
332
333 assert (bfd_get_flavour (outbfd) == bfd_target_nlm_flavour);
334
335 if (bfd_arch_get_compatible (inbfd, outbfd) == NULL)
336 fprintf (stderr,
337 "%s: warning:input and output formats are not compatible\n",
338 program_name);
339
340 /* Move the values read from the command file into outbfd. */
341 *nlm_fixed_header (outbfd) = fixed_hdr_struct;
342 *nlm_variable_header (outbfd) = var_hdr_struct;
343 *nlm_version_header (outbfd) = version_hdr_struct;
344 *nlm_copyright_header (outbfd) = copyright_hdr_struct;
345 *nlm_extended_header (outbfd) = extended_hdr_struct;
346
347 /* Start copying the input BFD to the output BFD. */
348 if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd)))
349 bfd_fatal (bfd_get_filename (outbfd));
350
351 symbols = (asymbol **) xmalloc (get_symtab_upper_bound (inbfd));
352 symcount = bfd_canonicalize_symtab (inbfd, symbols);
353
354 /* Make sure we have a .bss section. */
355 bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME);
356 if (bss_sec == NULL)
357 {
358 bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME);
359 if (bss_sec == NULL
360 || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC)
361 || ! bfd_set_section_alignment (outbfd, bss_sec, 1))
362 bfd_fatal ("make .bss section");
363 }
364
365 /* Set up the sections. */
366 bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);
367
368 /* The .bss section immediately follows the .data section. */
369 data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME);
370 if (data_sec != NULL)
371 {
372 bfd_size_type add;
373
374 vma = bfd_get_section_size_before_reloc (data_sec);
375 align = 1 << bss_sec->alignment_power;
376 add = ((vma + align - 1) &~ (align - 1)) - vma;
377 vma += add;
378 if (! bfd_set_section_vma (outbfd, bss_sec, vma))
379 bfd_fatal ("set .bss vma");
380 if (add != 0)
381 {
382 bfd_size_type data_size;
383
384 data_size = bfd_get_section_size_before_reloc (data_sec);
385 if (! bfd_set_section_size (outbfd, data_sec, data_size + add))
386 bfd_fatal ("set .data size");
387 }
388 }
389
390 /* Adjust symbol information. */
391 inlead = bfd_get_symbol_leading_char (inbfd);
392 outlead = bfd_get_symbol_leading_char (outbfd);
393 gotstart = false;
394 gotexit = false;
395 gotcheck = false;
396 newsymalloc = 10;
397 newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *));
398 newsymcount = 0;
399 endsym = NULL;
400 for (i = 0; i < symcount; i++)
401 {
402 register asymbol *sym;
403
404 sym = symbols[i];
405
406 /* Add or remove a leading underscore. */
407 if (inlead != outlead)
408 {
409 if (inlead != '\0')
410 {
411 if (bfd_asymbol_name (sym)[0] == inlead)
412 {
413 if (outlead == '\0')
414 ++sym->name;
415 else
416 {
417 char *new;
418
419 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1);
420 new[0] = outlead;
421 strcpy (new + 1, bfd_asymbol_name (sym) + 1);
422 sym->name = new;
423 }
424 }
425 }
426 else
427 {
428 char *new;
429
430 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2);
431 new[0] = outlead;
432 strcpy (new + 1, bfd_asymbol_name (sym));
433 sym->name = new;
434 }
435 }
436
437 /* NLM's have an uninitialized data section, but they do not
438 have a common section in the Unix sense. Move all common
439 symbols into the .bss section, and mark them as exported. */
440 if (bfd_is_com_section (bfd_get_section (sym)))
441 {
442 bfd_vma size;
443
444 sym->section = bss_sec;
445 size = sym->value;
446 sym->value = bss_sec->_raw_size;
447 bss_sec->_raw_size += size;
448 align = 1 << bss_sec->alignment_power;
449 bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1);
450 sym->flags |= BSF_EXPORT | BSF_GLOBAL;
451 }
452 else if (bfd_get_section (sym)->output_section != NULL)
453 {
454 /* Move the symbol into the output section. */
455 sym->value += bfd_get_section (sym)->output_offset;
456 sym->section = bfd_get_section (sym)->output_section;
457 /* This is no longer a section symbol. */
458 sym->flags &=~ BSF_SECTION_SYM;
459 }
460
461 /* Force _edata and _end to be defined. This would normally be
462 done by the linker, but the manipulation of the common
463 symbols will confuse it. */
464 if (bfd_asymbol_name (sym)[0] == '_'
465 && bfd_get_section (sym) == &bfd_und_section)
466 {
467 if (strcmp (bfd_asymbol_name (sym), "_edata") == 0)
468 {
469 sym->section = bss_sec;
470 sym->value = 0;
471 }
472 if (strcmp (bfd_asymbol_name (sym), "_end") == 0)
473 {
474 sym->section = bss_sec;
475 endsym = sym;
476 }
477 }
478
479 /* If this is a global symbol, check the export list. */
480 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0)
481 {
482 register struct string_list *l;
483 int found_simple;
484
485 /* Unfortunately, a symbol can appear multiple times on the
486 export list, with and without prefixes. */
487 found_simple = 0;
488 for (l = export_symbols; l != NULL; l = l->next)
489 {
490 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
491 found_simple = 1;
492 else
493 {
494 char *zbase;
495
496 zbase = strchr (l->string, '@');
497 if (zbase != NULL
498 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
499 {
500 /* We must add a symbol with this prefix. */
501 if (newsymcount >= newsymalloc)
502 {
503 newsymalloc += 10;
504 newsyms = ((asymbol **)
505 xrealloc ((PTR) newsyms,
506 (newsymalloc
507 * sizeof (asymbol *))));
508 }
509 newsyms[newsymcount] =
510 (asymbol *) xmalloc (sizeof (asymbol));
511 *newsyms[newsymcount] = *sym;
512 newsyms[newsymcount]->name = l->string;
513 ++newsymcount;
514 }
515 }
516 }
517 if (! found_simple)
518 {
519 /* The unmodified symbol is actually not exported at
520 all. */
521 sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT);
522 sym->flags |= BSF_LOCAL;
523 }
524 }
525
526 /* If it's an undefined symbol, see if it's on the import list.
527 Change the prefix if necessary. */
528 if (bfd_get_section (sym) == &bfd_und_section)
529 {
530 register struct string_list *l;
531
532 for (l = import_symbols; l != NULL; l = l->next)
533 {
534 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
535 break;
536 else
537 {
538 char *zbase;
539
540 zbase = strchr (l->string, '@');
541 if (zbase != NULL
542 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
543 {
544 sym->name = l->string;
545 break;
546 }
547 }
548 }
549 if (l == NULL)
550 fprintf (stderr,
551 "%s: warning: symbol %s imported but not in import list\n",
552 program_name, bfd_asymbol_name (sym));
553 }
554
555 /* See if it's one of the special named symbols. */
556 if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0)
557 {
558 if (! bfd_set_start_address (outbfd, bfd_asymbol_value (sym)))
559 bfd_fatal ("set start address");
560 gotstart = true;
561 }
562 if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0)
563 {
564 nlm_fixed_header (outbfd)->exitProcedureOffset =
565 bfd_asymbol_value (sym);
566 gotexit = true;
567 }
568 if (check_procedure != NULL
569 && strcmp (bfd_asymbol_name (sym), check_procedure) == 0)
570 {
571 nlm_fixed_header (outbfd)->checkUnloadProcedureOffset =
572 bfd_asymbol_value (sym);
573 gotcheck = true;
574 }
575 }
576
577 if (endsym != NULL)
578 endsym->value = bfd_get_section_size_before_reloc (bss_sec);
579
580 if (newsymcount == 0)
581 outsyms = symbols;
582 else
583 {
584 outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1)
585 * sizeof (asymbol *));
586 memcpy (outsyms, symbols, symcount * sizeof (asymbol *));
587 memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *));
588 outsyms[symcount + newsymcount] = NULL;
589 }
590
591 bfd_set_symtab (outbfd, outsyms, symcount + newsymcount);
592
593 if (! gotstart)
594 fprintf (stderr, "%s: warning: START procedure %s not defined\n",
595 program_name, start_procedure);
596 if (! gotexit)
597 fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n",
598 program_name, exit_procedure);
599 if (check_procedure != NULL
600 && ! gotcheck)
601 fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n",
602 program_name, check_procedure);
603
604 /* Add additional sections required for the header information. */
605 if (custom_file != NULL)
606 {
607 custom_data = fopen (custom_file, "r");
608 if (custom_data == NULL
609 || fstat (fileno (custom_data), &st) < 0)
610 {
611 fprintf (stderr, "%s:%s: %s\n", program_name, custom_file,
612 strerror (errno));
613 custom_file = NULL;
614 }
615 else
616 {
617 custom_size = st.st_size;
618 custom_section = bfd_make_section (outbfd, ".nlmcustom");
619 if (custom_section == NULL
620 || ! bfd_set_section_size (outbfd, custom_section, custom_size)
621 || ! bfd_set_section_flags (outbfd, custom_section,
622 SEC_HAS_CONTENTS))
623 bfd_fatal ("custom section");
624 }
625 }
626 if (help_file != NULL)
627 {
628 help_data = fopen (help_file, "r");
629 if (help_data == NULL
630 || fstat (fileno (help_data), &st) < 0)
631 {
632 fprintf (stderr, "%s:%s: %s\n", program_name, help_file,
633 strerror (errno));
634 help_file = NULL;
635 }
636 else
637 {
638 help_size = st.st_size;
639 help_section = bfd_make_section (outbfd, ".nlmhelp");
640 if (help_section == NULL
641 || ! bfd_set_section_size (outbfd, help_section, help_size)
642 || ! bfd_set_section_flags (outbfd, help_section,
643 SEC_HAS_CONTENTS))
644 bfd_fatal ("help section");
645 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
646 }
647 }
648 if (message_file != NULL)
649 {
650 message_data = fopen (message_file, "r");
651 if (message_data == NULL
652 || fstat (fileno (message_data), &st) < 0)
653 {
654 fprintf (stderr, "%s:%s: %s\n", program_name, message_file,
655 strerror (errno));
656 message_file = NULL;
657 }
658 else
659 {
660 message_size = st.st_size;
661 message_section = bfd_make_section (outbfd, ".nlmmessages");
662 if (message_section == NULL
663 || ! bfd_set_section_size (outbfd, message_section, message_size)
664 || ! bfd_set_section_flags (outbfd, message_section,
665 SEC_HAS_CONTENTS))
666 bfd_fatal ("message section");
667 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
668 }
669 }
670 if (modules != NULL)
671 {
672 struct string_list *l;
673
674 module_size = 0;
675 for (l = modules; l != NULL; l = l->next)
676 module_size += strlen (l->string) + 1;
677 module_section = bfd_make_section (outbfd, ".nlmmodules");
678 if (module_section == NULL
679 || ! bfd_set_section_size (outbfd, module_section, module_size)
680 || ! bfd_set_section_flags (outbfd, module_section,
681 SEC_HAS_CONTENTS))
682 bfd_fatal ("module section");
683 }
684 if (rpc_file != NULL)
685 {
686 rpc_data = fopen (rpc_file, "r");
687 if (rpc_data == NULL
688 || fstat (fileno (rpc_data), &st) < 0)
689 {
690 fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file,
691 strerror (errno));
692 rpc_file = NULL;
693 }
694 else
695 {
696 rpc_size = st.st_size;
697 rpc_section = bfd_make_section (outbfd, ".nlmrpc");
698 if (rpc_section == NULL
699 || ! bfd_set_section_size (outbfd, rpc_section, rpc_size)
700 || ! bfd_set_section_flags (outbfd, rpc_section,
701 SEC_HAS_CONTENTS))
702 bfd_fatal ("rpc section");
703 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
704 }
705 }
706 if (sharelib_file != NULL)
707 {
708 sharedbfd = bfd_openr (sharelib_file, output_format);
709 if (sharedbfd == NULL
710 || ! bfd_check_format (sharedbfd, bfd_object))
711 {
712 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
713 bfd_errmsg (bfd_error));
714 sharelib_file = NULL;
715 }
716 else
717 {
718 sharedhdr = *nlm_fixed_header (sharedbfd);
719 bfd_close (sharedbfd);
720 shared_data = fopen (sharelib_file, "r");
721 if (shared_data == NULL
722 || (fstat (fileno (shared_data), &st) < 0))
723 {
724 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
725 strerror (errno));
726 sharelib_file = NULL;
727 }
728 else
729 {
730 /* If we were clever, we could just copy out the
731 sections of the shared library which we actually
732 need. However, we would have to figure out the sizes
733 of the external and public information, and that can
734 not be done without reading through them. */
735 if (sharedhdr.uninitializedDataSize > 0)
736 {
737 /* There is no place to record this information. */
738 fprintf (stderr,
739 "%s:%s: warning: shared libraries can not have uninitialized data\n",
740 program_name, sharelib_file);
741 }
742 shared_offset = st.st_size;
743 if (shared_offset > sharedhdr.codeImageOffset)
744 shared_offset = sharedhdr.codeImageOffset;
745 if (shared_offset > sharedhdr.dataImageOffset)
746 shared_offset = sharedhdr.dataImageOffset;
747 if (shared_offset > sharedhdr.relocationFixupOffset)
748 shared_offset = sharedhdr.relocationFixupOffset;
749 if (shared_offset > sharedhdr.externalReferencesOffset)
750 shared_offset = sharedhdr.externalReferencesOffset;
751 if (shared_offset > sharedhdr.publicsOffset)
752 shared_offset = sharedhdr.publicsOffset;
753 shared_size = st.st_size - shared_offset;
754 shared_section = bfd_make_section (outbfd, ".nlmshared");
755 if (shared_section == NULL
756 || ! bfd_set_section_size (outbfd, shared_section,
757 shared_size)
758 || ! bfd_set_section_flags (outbfd, shared_section,
759 SEC_HAS_CONTENTS))
760 bfd_fatal ("shared section");
761 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
762 }
763 }
764 }
765
766 /* Check whether a version was given. */
767 if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0)
768 fprintf (stderr, "%s: warning: No version number given\n",
769 program_name);
770
771 /* At least for now, always create an extended header, because that
772 is what NLMLINK does. */
773 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
774
775 /* If the date was not given, force it in. */
776 if (nlm_version_header (outbfd)->month == 0
777 && nlm_version_header (outbfd)->day == 0
778 && nlm_version_header (outbfd)->year == 0)
779 {
780 time_t now;
781 struct tm *ptm;
782
783 time (&now);
784 ptm = localtime (&now);
785 nlm_version_header (outbfd)->month = ptm->tm_mon + 1;
786 nlm_version_header (outbfd)->day = ptm->tm_mday;
787 nlm_version_header (outbfd)->year = ptm->tm_year + 1900;
788 strncpy (version_hdr->stamp, "VeRsIoN#", 8);
789 }
790
791 /* Copy over the sections. */
792 bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd);
793
794 /* Finish up the header information. */
795 if (custom_file != NULL)
796 {
797 PTR data;
798
799 data = xmalloc (custom_size);
800 if (fread (data, 1, custom_size, custom_data) != custom_size)
801 fprintf (stderr, "%s:%s: read: %s\n", program_name, custom_file,
802 strerror (errno));
803 else
804 {
805 if (! bfd_set_section_contents (outbfd, custom_section, data,
806 (file_ptr) 0, custom_size))
807 bfd_fatal ("custom section");
808 nlm_fixed_header (outbfd)->customDataOffset =
809 custom_section->filepos;
810 nlm_fixed_header (outbfd)->customDataSize = custom_size;
811 }
812 free (data);
813 }
814 if (! debug_info)
815 {
816 /* As a special hack, the backend recognizes a debugInfoOffset
817 of -1 to mean that it should not output any debugging
818 information. This can not be handling by fiddling with the
819 symbol table because exported symbols appear in both the
820 export information and the debugging information. */
821 nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1;
822 }
823 if (map_file != NULL)
824 fprintf (stderr,
825 "%s: warning: MAP and FULLMAP are not supported; try ld -M\n",
826 program_name);
827 if (help_file != NULL)
828 {
829 PTR data;
830
831 data = xmalloc (help_size);
832 if (fread (data, 1, help_size, help_data) != help_size)
833 fprintf (stderr, "%s:%s: read: %s\n", program_name, help_file,
834 strerror (errno));
835 else
836 {
837 if (! bfd_set_section_contents (outbfd, help_section, data,
838 (file_ptr) 0, help_size))
839 bfd_fatal ("help section");
840 nlm_extended_header (outbfd)->helpFileOffset =
841 help_section->filepos;
842 nlm_extended_header (outbfd)->helpFileLength = help_size;
843 }
844 free (data);
845 }
846 if (message_file != NULL)
847 {
848 PTR data;
849
850 data = xmalloc (message_size);
851 if (fread (data, 1, message_size, message_data) != message_size)
852 fprintf (stderr, "%s:%s: read: %s\n", program_name, message_file,
853 strerror (errno));
854 else
855 {
856 if (! bfd_set_section_contents (outbfd, message_section, data,
857 (file_ptr) 0, message_size))
858 bfd_fatal ("message section");
859 nlm_extended_header (outbfd)->messageFileOffset =
860 message_section->filepos;
861 nlm_extended_header (outbfd)->messageFileLength = message_size;
862
863 /* FIXME: Are these offsets correct on all platforms? Are
864 they 32 bits on all platforms? What endianness? */
865 nlm_extended_header (outbfd)->languageID =
866 bfd_h_get_32 (outbfd, (bfd_byte *) data + 106);
867 nlm_extended_header (outbfd)->messageCount =
868 bfd_h_get_32 (outbfd, (bfd_byte *) data + 110);
869 }
870 free (data);
871 }
872 if (modules != NULL)
873 {
874 PTR data;
875 unsigned char *set;
876 struct string_list *l;
877 bfd_size_type c;
878
879 data = xmalloc (module_size);
880 c = 0;
881 set = (unsigned char *) data;
882 for (l = modules; l != NULL; l = l->next)
883 {
884 *set = strlen (l->string);
885 strncpy (set + 1, l->string, *set);
886 set += *set + 1;
887 ++c;
888 }
889 if (! bfd_set_section_contents (outbfd, module_section, data,
890 (file_ptr) 0, module_size))
891 bfd_fatal ("module section");
892 nlm_fixed_header (outbfd)->moduleDependencyOffset =
893 module_section->filepos;
894 nlm_fixed_header (outbfd)->numberOfModuleDependencies = c;
895 }
896 if (rpc_file != NULL)
897 {
898 PTR data;
899
900 data = xmalloc (rpc_size);
901 if (fread (data, 1, rpc_size, rpc_data) != rpc_size)
902 fprintf (stderr, "%s:%s: read: %s\n", program_name, rpc_file,
903 strerror (errno));
904 else
905 {
906 if (! bfd_set_section_contents (outbfd, rpc_section, data,
907 (file_ptr) 0, rpc_size))
908 bfd_fatal ("rpc section");
909 nlm_extended_header (outbfd)->RPCDataOffset =
910 rpc_section->filepos;
911 nlm_extended_header (outbfd)->RPCDataLength = rpc_size;
912 }
913 free (data);
914 }
915 if (sharelib_file != NULL)
916 {
917 PTR data;
918
919 data = xmalloc (shared_size);
920 if (fseek (shared_data, shared_offset, SEEK_SET) != 0
921 || fread (data, 1, shared_size, shared_data) != shared_size)
922 fprintf (stderr, "%s:%s: read: %s\n", program_name, sharelib_file,
923 strerror (errno));
924 else
925 {
926 if (! bfd_set_section_contents (outbfd, shared_section, data,
927 (file_ptr) 0, shared_size))
928 bfd_fatal ("shared section");
929 }
930 nlm_extended_header (outbfd)->sharedCodeOffset =
931 sharedhdr.codeImageOffset - shared_offset + shared_section->filepos;
932 nlm_extended_header (outbfd)->sharedCodeLength =
933 sharedhdr.codeImageSize;
934 nlm_extended_header (outbfd)->sharedDataOffset =
935 sharedhdr.dataImageOffset - shared_offset + shared_section->filepos;
936 nlm_extended_header (outbfd)->sharedDataLength =
937 sharedhdr.dataImageSize;
938 nlm_extended_header (outbfd)->sharedRelocationFixupOffset =
939 (sharedhdr.relocationFixupOffset
940 - shared_offset
941 + shared_section->filepos);
942 nlm_extended_header (outbfd)->sharedRelocationFixupCount =
943 sharedhdr.numberOfRelocationFixups;
944 nlm_extended_header (outbfd)->sharedExternalReferenceOffset =
945 (sharedhdr.externalReferencesOffset
946 - shared_offset
947 + shared_section->filepos);
948 nlm_extended_header (outbfd)->sharedExternalReferenceCount =
949 sharedhdr.numberOfExternalReferences;
950 nlm_extended_header (outbfd)->sharedPublicsOffset =
951 sharedhdr.publicsOffset - shared_offset + shared_section->filepos;
952 nlm_extended_header (outbfd)->sharedPublicsCount =
953 sharedhdr.numberOfPublics;
954 nlm_extended_header (outbfd)->sharedDebugRecordOffset =
955 sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos;
956 nlm_extended_header (outbfd)->sharedDebugRecordCount =
957 sharedhdr.numberOfDebugRecords;
958 nlm_extended_header (outbfd)->SharedInitializationOffset =
959 sharedhdr.codeStartOffset;
960 nlm_extended_header (outbfd)->SharedExitProcedureOffset =
961 sharedhdr.exitProcedureOffset;
962 free (data);
963 }
964 len = strlen (output_file);
965 if (len > NLM_MODULE_NAME_SIZE - 2)
966 len = NLM_MODULE_NAME_SIZE - 2;
967 nlm_fixed_header (outbfd)->moduleName[0] = len;
968
969 strncpy (nlm_fixed_header (outbfd)->moduleName + 1, output_file,
970 NLM_MODULE_NAME_SIZE - 2);
971 nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0';
972 for (modname = nlm_fixed_header (outbfd)->moduleName;
973 *modname != '\0';
974 modname++)
975 if (islower (*modname))
976 *modname = toupper (*modname);
977
978 strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
979 NLM_OLD_THREAD_NAME_LENGTH);
980
981 if (! bfd_close (outbfd))
982 bfd_fatal (output_file);
983 if (! bfd_close (inbfd))
984 bfd_fatal (input_file);
985
986 if (unlink_on_exit != NULL)
987 unlink (unlink_on_exit);
988
989 return 0;
990 }
991 \f
992 /* Display a help message and exit. */
993
994 static void
995 show_help ()
996 {
997 printf ("%s: Convert an object file into a NetWare Loadable Module\n",
998 program_name);
999 show_usage (stdout, 0);
1000 }
1001
1002 /* Show a usage message and exit. */
1003
1004 static void
1005 show_usage (file, status)
1006 FILE *file;
1007 int status;
1008 {
1009 fprintf (file, "\
1010 Usage: %s [-dhV] [-I bfdname] [-O bfdname] [-T header-file] [-l linker]\n\
1011 [--input-target=bfdname] [--output-target=bfdname]\n\
1012 [--header-file=file] [--linker=linker] [--debug]\n\
1013 [--help] [--version]\n\
1014 [in-file [out-file]]\n",
1015 program_name);
1016 exit (status);
1017 }
1018 \f
1019 /* Select the output format based on the input architecture, machine,
1020 and endianness. This chooses the appropriate NLM target. */
1021
1022 static const char *
1023 select_output_format (arch, mach, bigendian)
1024 enum bfd_architecture arch;
1025 unsigned long mach;
1026 boolean bigendian;
1027 {
1028 switch (arch)
1029 {
1030 case bfd_arch_i386:
1031 return "nlm32-i386";
1032 case bfd_arch_sparc:
1033 return "nlm32-sparc";
1034 case bfd_arch_alpha:
1035 return "nlm32-alpha";
1036 default:
1037 fprintf (stderr, "%s: no default NLM format for %s\n",
1038 program_name, bfd_printable_arch_mach (arch, mach));
1039 exit (1);
1040 /* Avoid warning. */
1041 return NULL;
1042 }
1043 /*NOTREACHED*/
1044 }
1045 \f
1046 /* The BFD sections are copied in two passes. This function selects
1047 the output section for each input section, and sets up the section
1048 name, size, etc. */
1049
1050 static void
1051 setup_sections (inbfd, insec, data_ptr)
1052 bfd *inbfd;
1053 asection *insec;
1054 PTR data_ptr;
1055 {
1056 bfd *outbfd = (bfd *) data_ptr;
1057 flagword f;
1058 const char *outname;
1059 asection *outsec;
1060 bfd_vma offset;
1061 bfd_size_type align;
1062 bfd_size_type add;
1063
1064 /* FIXME: We don't want to copy the .reginfo section of an ECOFF
1065 file. However, I don't have a good way to describe this section.
1066 We do want to copy the section when using objcopy. */
1067 if (bfd_get_flavour (inbfd) == bfd_target_ecoff_flavour
1068 && strcmp (bfd_section_name (inbfd, insec), ".reginfo") == 0)
1069 return;
1070
1071 f = bfd_get_section_flags (inbfd, insec);
1072 if (f & SEC_CODE)
1073 outname = NLM_CODE_NAME;
1074 else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS))
1075 outname = NLM_INITIALIZED_DATA_NAME;
1076 else if (f & SEC_ALLOC)
1077 outname = NLM_UNINITIALIZED_DATA_NAME;
1078 else
1079 outname = bfd_section_name (inbfd, insec);
1080
1081 outsec = bfd_get_section_by_name (outbfd, outname);
1082 if (outsec == NULL)
1083 {
1084 outsec = bfd_make_section (outbfd, outname);
1085 if (outsec == NULL)
1086 bfd_fatal ("make section");
1087 }
1088
1089 insec->output_section = outsec;
1090
1091 offset = bfd_section_size (outbfd, outsec);
1092 align = 1 << bfd_section_alignment (inbfd, insec);
1093 add = ((offset + align - 1) &~ (align - 1)) - offset;
1094 insec->output_offset = offset + add;
1095
1096 if (! bfd_set_section_size (outbfd, outsec,
1097 (bfd_section_size (outbfd, outsec)
1098 + bfd_section_size (inbfd, insec)
1099 + add)))
1100 bfd_fatal ("set section size");
1101
1102 if ((bfd_section_alignment (inbfd, insec)
1103 > bfd_section_alignment (outbfd, outsec))
1104 && ! bfd_set_section_alignment (outbfd, outsec,
1105 bfd_section_alignment (inbfd, insec)))
1106 bfd_fatal ("set section alignment");
1107
1108 if (! bfd_set_section_flags (outbfd, outsec, f))
1109 bfd_fatal ("set section flags");
1110
1111 bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
1112 }
1113
1114 /* Copy the section contents. */
1115
1116 static void
1117 copy_sections (inbfd, insec, data_ptr)
1118 bfd *inbfd;
1119 asection *insec;
1120 PTR data_ptr;
1121 {
1122 bfd *outbfd = (bfd *) data_ptr;
1123 asection *outsec;
1124 bfd_size_type size;
1125 PTR contents;
1126 bfd_size_type reloc_size;
1127
1128 /* FIXME: We don't want to copy the .reginfo section of an ECOFF
1129 file. However, I don't have a good way to describe this section.
1130 We do want to copy the section when using objcopy. */
1131 if (bfd_get_flavour (inbfd) == bfd_target_ecoff_flavour
1132 && strcmp (bfd_section_name (inbfd, insec), ".reginfo") == 0)
1133 return;
1134
1135 outsec = insec->output_section;
1136 assert (outsec != NULL);
1137
1138 size = bfd_get_section_size_before_reloc (insec);
1139 if (size == 0)
1140 return;
1141
1142 /* FIXME: Why are these necessary? */
1143 insec->_cooked_size = insec->_raw_size;
1144 insec->reloc_done = true;
1145
1146 if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
1147 contents = NULL;
1148 else
1149 {
1150 contents = xmalloc (size);
1151 if (! bfd_get_section_contents (inbfd, insec, contents,
1152 (file_ptr) 0, size))
1153 bfd_fatal (bfd_get_filename (inbfd));
1154 }
1155
1156 reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
1157 if (reloc_size != 0)
1158 {
1159 arelent **relocs;
1160 bfd_size_type reloc_count;
1161
1162 relocs = (arelent **) xmalloc (reloc_size);
1163 reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols);
1164 mangle_relocs (outbfd, insec, &relocs, &reloc_count, (char *) contents,
1165 size);
1166
1167 /* FIXME: refers to internal BFD fields. */
1168 if (outsec->orelocation != (arelent **) NULL)
1169 {
1170 bfd_size_type total_count;
1171 arelent **combined;
1172
1173 total_count = reloc_count + outsec->reloc_count;
1174 combined = (arelent **) xmalloc (total_count * sizeof (arelent));
1175 memcpy (combined, outsec->orelocation,
1176 outsec->reloc_count * sizeof (arelent));
1177 memcpy (combined + outsec->reloc_count, relocs,
1178 (size_t) (reloc_count * sizeof (arelent)));
1179 free (outsec->orelocation);
1180 reloc_count = total_count;
1181 relocs = combined;
1182 }
1183
1184 bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
1185 }
1186
1187 if (contents != NULL)
1188 {
1189 if (! bfd_set_section_contents (outbfd, outsec, contents,
1190 insec->output_offset, size))
1191 bfd_fatal (bfd_get_filename (outbfd));
1192 free (contents);
1193 }
1194 }
1195
1196 /* Some, perhaps all, NetWare targets require changing the relocs used
1197 by the input formats. */
1198
1199 static void
1200 mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1201 contents_size)
1202 bfd *outbfd;
1203 asection *insec;
1204 arelent ***relocs_ptr;
1205 bfd_size_type *reloc_count_ptr;
1206 char *contents;
1207 bfd_size_type contents_size;
1208 {
1209 switch (bfd_get_arch (outbfd))
1210 {
1211 case bfd_arch_i386:
1212 i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1213 contents, contents_size);
1214 break;
1215 case bfd_arch_alpha:
1216 alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1217 contents, contents_size);
1218 break;
1219 default:
1220 default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1221 contents, contents_size);
1222 break;
1223 }
1224 }
1225
1226 /* By default all we need to do for relocs is change the address by
1227 the output_offset. */
1228
1229 /*ARGSUSED*/
1230 static void
1231 default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1232 contents_size)
1233 bfd *outbfd;
1234 asection *insec;
1235 arelent ***relocs_ptr;
1236 bfd_size_type *reloc_count_ptr;
1237 char *contents;
1238 bfd_size_type contents_size;
1239 {
1240 if (insec->output_offset != 0)
1241 {
1242 bfd_size_type reloc_count;
1243 register arelent **relocs;
1244 register bfd_size_type i;
1245
1246 reloc_count = *reloc_count_ptr;
1247 relocs = *relocs_ptr;
1248 for (i = 0; i < reloc_count; i++, relocs++)
1249 (*relocs)->address += insec->output_offset;
1250 }
1251 }
1252
1253 /* NetWare on the i386 supports a restricted set of relocs, which are
1254 different from those used on other i386 targets. This routine
1255 converts the relocs. It is, obviously, very target dependent. At
1256 the moment, the nlm32-i386 backend performs similar translations;
1257 however, it is more reliable and efficient to do them here. */
1258
1259 static reloc_howto_type nlm_i386_pcrel_howto =
1260 HOWTO (1, /* type */
1261 0, /* rightshift */
1262 2, /* size (0 = byte, 1 = short, 2 = long) */
1263 32, /* bitsize */
1264 true, /* pc_relative */
1265 0, /* bitpos */
1266 complain_overflow_signed, /* complain_on_overflow */
1267 0, /* special_function */
1268 "DISP32", /* name */
1269 true, /* partial_inplace */
1270 0xffffffff, /* src_mask */
1271 0xffffffff, /* dst_mask */
1272 true); /* pcrel_offset */
1273
1274 static void
1275 i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1276 contents_size)
1277 bfd *outbfd;
1278 asection *insec;
1279 arelent ***relocs_ptr;
1280 bfd_size_type *reloc_count_ptr;
1281 char *contents;
1282 bfd_size_type contents_size;
1283 {
1284 bfd_size_type reloc_count, i;
1285 arelent **relocs;
1286
1287 reloc_count = *reloc_count_ptr;
1288 relocs = *relocs_ptr;
1289 for (i = 0; i < reloc_count; i++)
1290 {
1291 arelent *rel;
1292 asymbol *sym;
1293 bfd_size_type address;
1294 bfd_vma addend;
1295
1296 rel = *relocs++;
1297 sym = *rel->sym_ptr_ptr;
1298
1299 /* We're moving the relocs from the input section to the output
1300 section, so we must adjust the address accordingly. */
1301 address = rel->address;
1302 rel->address += insec->output_offset;
1303
1304 /* Note that no serious harm will ensue if we fail to change a
1305 reloc. The backend will fail when writing out the reloc. */
1306
1307 /* Make sure this reloc is within the data we have. We use only
1308 4 byte relocs here, so we insist on having 4 bytes. */
1309 if (address + 4 > contents_size)
1310 continue;
1311
1312 /* A PC relative reloc entirely within a single section is
1313 completely unnecessary. This can be generated by ld -r. */
1314 if (sym == insec->symbol
1315 && rel->howto != NULL
1316 && rel->howto->pc_relative
1317 && ! rel->howto->pcrel_offset)
1318 {
1319 --*reloc_count_ptr;
1320 --relocs;
1321 memmove (relocs, relocs + 1,
1322 (size_t) ((reloc_count - i) * sizeof (arelent *)));
1323 continue;
1324 }
1325
1326 /* Get the amount the relocation will add in. */
1327 addend = rel->addend + sym->value;
1328
1329 /* NetWare doesn't support PC relative relocs against defined
1330 symbols, so we have to eliminate them by doing the relocation
1331 now. We can only do this if the reloc is within a single
1332 section. */
1333 if (rel->howto != NULL
1334 && rel->howto->pc_relative
1335 && bfd_get_section (sym) == insec->output_section)
1336 {
1337 bfd_vma val;
1338
1339 if (rel->howto->pcrel_offset)
1340 addend -= address;
1341
1342 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1343 val += addend;
1344 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1345
1346 --*reloc_count_ptr;
1347 --relocs;
1348 memmove (relocs, relocs + 1,
1349 (size_t) ((reloc_count - i) * sizeof (arelent *)));
1350 continue;
1351 }
1352
1353 /* NetWare doesn't support reloc addends, so we get rid of them
1354 here by simply adding them into the object data. We handle
1355 the symbol value, if any, the same way. */
1356 if (addend != 0
1357 && rel->howto != NULL
1358 && rel->howto->rightshift == 0
1359 && rel->howto->size == 2
1360 && rel->howto->bitsize == 32
1361 && rel->howto->bitpos == 0
1362 && rel->howto->src_mask == 0xffffffff
1363 && rel->howto->dst_mask == 0xffffffff)
1364 {
1365 bfd_vma val;
1366
1367 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1368 val += addend;
1369 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1370
1371 /* Adjust the reloc for the changes we just made. */
1372 rel->addend = 0;
1373 if (bfd_get_section (sym) != &bfd_und_section)
1374 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
1375 }
1376
1377 /* NetWare uses a reloc with pcrel_offset set. We adjust
1378 pc_relative relocs accordingly. We are going to change the
1379 howto field, so we can only do this if the current one is
1380 compatible. We should check that special_function is NULL
1381 here, but at the moment coff-i386 uses a special_function
1382 which does not affect what we are doing here. */
1383 if (rel->howto != NULL
1384 && rel->howto->pc_relative
1385 && ! rel->howto->pcrel_offset
1386 && rel->howto->rightshift == 0
1387 && rel->howto->size == 2
1388 && rel->howto->bitsize == 32
1389 && rel->howto->bitpos == 0
1390 && rel->howto->src_mask == 0xffffffff
1391 && rel->howto->dst_mask == 0xffffffff)
1392 {
1393 bfd_vma val;
1394
1395 /* When pcrel_offset is not set, it means that the negative
1396 of the address of the memory location is stored in the
1397 memory location. We must add it back in. */
1398 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1399 val += address;
1400 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1401
1402 /* We must change to a new howto. */
1403 rel->howto = &nlm_i386_pcrel_howto;
1404 }
1405 }
1406 }
1407
1408 /* On the Alpha the first reloc for every section must be a special
1409 relocs which hold the GP address. Also, the first reloc in the
1410 file must be a special reloc which holds the address of the .lita
1411 section. */
1412
1413 static reloc_howto_type nlm32_alpha_nw_howto =
1414 HOWTO (ALPHA_R_NW_RELOC, /* type */
1415 0, /* rightshift */
1416 0, /* size (0 = byte, 1 = short, 2 = long) */
1417 0, /* bitsize */
1418 false, /* pc_relative */
1419 0, /* bitpos */
1420 complain_overflow_dont, /* complain_on_overflow */
1421 0, /* special_function */
1422 "NW_RELOC", /* name */
1423 false, /* partial_inplace */
1424 0, /* src_mask */
1425 0, /* dst_mask */
1426 false); /* pcrel_offset */
1427
1428 /*ARGSUSED*/
1429 static void
1430 alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1431 contents_size)
1432 bfd *outbfd;
1433 asection *insec;
1434 register arelent ***relocs_ptr;
1435 bfd_size_type *reloc_count_ptr;
1436 char *contents;
1437 bfd_size_type contents_size;
1438 {
1439 bfd_size_type old_reloc_count;
1440 arelent **old_relocs;
1441 register arelent **relocs;
1442
1443 old_reloc_count = *reloc_count_ptr;
1444 old_relocs = *relocs_ptr;
1445 relocs = (arelent **) xmalloc ((old_reloc_count + 3) * sizeof (arelent *));
1446 *relocs_ptr = relocs;
1447
1448 if (nlm_alpha_backend_data (outbfd)->lita_address == 0)
1449 {
1450 bfd *inbfd;
1451 asection *lita_section;
1452
1453 inbfd = insec->owner;
1454 lita_section = bfd_get_section_by_name (inbfd, _LITA);
1455 if (lita_section != (asection *) NULL)
1456 {
1457 nlm_alpha_backend_data (outbfd)->lita_address =
1458 bfd_get_section_vma (inbfd, lita_section);
1459 nlm_alpha_backend_data (outbfd)->lita_size =
1460 bfd_section_size (inbfd, lita_section);
1461 }
1462 else
1463 {
1464 /* Avoid outputting this reloc again. */
1465 nlm_alpha_backend_data (outbfd)->lita_address = 4;
1466 }
1467
1468 *relocs = (arelent *) xmalloc (sizeof (arelent));
1469 (*relocs)->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
1470 (*relocs)->address = nlm_alpha_backend_data (outbfd)->lita_address;
1471 (*relocs)->addend = nlm_alpha_backend_data (outbfd)->lita_size + 1;
1472 (*relocs)->howto = &nlm32_alpha_nw_howto;
1473 ++relocs;
1474 ++(*reloc_count_ptr);
1475 }
1476
1477 /* Get the GP value from bfd. It is in the .reginfo section. */
1478 if (nlm_alpha_backend_data (outbfd)->gp == 0)
1479 {
1480 bfd *inbfd;
1481 asection *reginfo_sec;
1482 struct ecoff_reginfo sreginfo;
1483
1484 inbfd = insec->owner;
1485 assert (bfd_get_flavour (inbfd) == bfd_target_ecoff_flavour);
1486 reginfo_sec = bfd_get_section_by_name (inbfd, REGINFO);
1487 if (reginfo_sec != (asection *) NULL
1488 && bfd_get_section_contents (inbfd, reginfo_sec,
1489 (PTR) &sreginfo, (file_ptr) 0,
1490 sizeof sreginfo) != false)
1491 nlm_alpha_backend_data (outbfd)->gp = sreginfo.gp_value;
1492 }
1493
1494 *relocs = (arelent *) xmalloc (sizeof (arelent));
1495 (*relocs)->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
1496 (*relocs)->address = nlm_alpha_backend_data (outbfd)->gp;
1497 (*relocs)->addend = 0;
1498 (*relocs)->howto = &nlm32_alpha_nw_howto;
1499 ++relocs;
1500 ++(*reloc_count_ptr);
1501
1502 memcpy ((PTR) relocs, (PTR) old_relocs,
1503 (size_t) old_reloc_count * sizeof (arelent *));
1504 relocs[old_reloc_count] = (arelent *) NULL;
1505
1506 free (old_relocs);
1507
1508 if (insec->output_offset != 0)
1509 {
1510 register bfd_size_type i;
1511
1512 for (i = 0; i < old_reloc_count; i++, relocs++)
1513 (*relocs)->address += insec->output_offset;
1514 }
1515 }
1516 \f
1517 /* Name of linker. */
1518 #ifndef LD_NAME
1519 #define LD_NAME "ld"
1520 #endif
1521
1522 /* Temporary file name base. */
1523 static char *temp_filename;
1524
1525 /* The user has specified several input files. Invoke the linker to
1526 link them all together, and convert and delete the resulting output
1527 file. */
1528
1529 static char *
1530 link_inputs (inputs, ld)
1531 struct string_list *inputs;
1532 char *ld;
1533 {
1534 size_t c;
1535 struct string_list *q;
1536 char **argv;
1537 size_t i;
1538 int pid;
1539 int status;
1540
1541 c = 0;
1542 for (q = inputs; q != NULL; q = q->next)
1543 ++c;
1544
1545 argv = (char **) alloca (c + 5);
1546
1547 #ifndef __MSDOS__
1548 if (ld == NULL)
1549 {
1550 char *p;
1551
1552 /* Find the linker to invoke based on how nlmconv was run. */
1553 p = program_name + strlen (program_name);
1554 while (p != program_name)
1555 {
1556 if (p[-1] == '/')
1557 {
1558 ld = (char *) xmalloc (p - program_name + strlen (LD_NAME) + 1);
1559 memcpy (ld, program_name, p - program_name);
1560 strcpy (ld + (p - program_name), LD_NAME);
1561 break;
1562 }
1563 --p;
1564 }
1565 }
1566 #endif
1567
1568 if (ld == NULL)
1569 ld = (char *) LD_NAME;
1570
1571 choose_temp_base ();
1572
1573 unlink_on_exit = xmalloc (strlen (temp_filename) + 3);
1574 sprintf (unlink_on_exit, "%s.O", temp_filename);
1575
1576 argv[0] = ld;
1577 argv[1] = (char *) "-r";
1578 argv[2] = (char *) "-o";
1579 argv[3] = unlink_on_exit;
1580 i = 4;
1581 for (q = inputs; q != NULL; q = q->next, i++)
1582 argv[i] = q->string;
1583 argv[i] = NULL;
1584
1585 if (debug)
1586 {
1587 for (i = 0; argv[i] != NULL; i++)
1588 fprintf (stderr, " %s", argv[i]);
1589 fprintf (stderr, "\n");
1590 }
1591
1592 pid = pexecute (ld, argv);
1593
1594 if (waitpid (pid, &status, 0) < 0)
1595 {
1596 perror ("waitpid");
1597 unlink (unlink_on_exit);
1598 exit (1);
1599 }
1600
1601 if (status != 0)
1602 {
1603 fprintf (stderr, "%s: Execution of %s failed\n", program_name, ld);
1604 unlink (unlink_on_exit);
1605 exit (1);
1606 }
1607
1608 return unlink_on_exit;
1609 }
1610
1611 /* Choose a temporary file name. Stolen from gcc.c. */
1612
1613 static const char *
1614 choose_temp_base_try (try, base)
1615 const char *try;
1616 const char *base;
1617 {
1618 const char *rv;
1619
1620 if (base)
1621 rv = base;
1622 else if (try == NULL)
1623 rv = NULL;
1624 else if (access (try, R_OK | W_OK) != 0)
1625 rv = NULL;
1626 else
1627 rv = try;
1628 return rv;
1629 }
1630
1631 static void
1632 choose_temp_base ()
1633 {
1634 const char *base = NULL;
1635 int len;
1636
1637 base = choose_temp_base_try (getenv ("TMPDIR"), base);
1638 base = choose_temp_base_try (getenv ("TMP"), base);
1639 base = choose_temp_base_try (getenv ("TEMP"), base);
1640
1641 #ifdef P_tmpdir
1642 base = choose_temp_base_try (P_tmpdir, base);
1643 #endif
1644
1645 base = choose_temp_base_try ("/usr/tmp", base);
1646 base = choose_temp_base_try ("/tmp", base);
1647
1648 /* If all else fails, use the current directory! */
1649 if (base == NULL)
1650 base = "./";
1651
1652 len = strlen (base);
1653 temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1);
1654 strcpy (temp_filename, base);
1655 if (len > 0 && temp_filename[len-1] != '/')
1656 temp_filename[len++] = '/';
1657 strcpy (temp_filename + len, "ccXXXXXX");
1658
1659 mktemp (temp_filename);
1660 if (*temp_filename == '\0')
1661 abort ();
1662 }
1663
1664 /* Execute a job. Stolen from gcc.c. */
1665
1666 #ifndef OS2
1667 #ifdef __MSDOS__
1668
1669 static int
1670 pexecute (program, argv)
1671 char *program;
1672 char *argv[];
1673 {
1674 char *scmd, *rf;
1675 FILE *argfile;
1676 int i;
1677
1678 scmd = (char *)malloc (strlen (program) + strlen (temp_filename) + 10);
1679 rf = scmd + strlen(program) + 2 + el;
1680 sprintf (scmd, "%s.exe @%s.gp", program, temp_filename);
1681 argfile = fopen (rf, "w");
1682 if (argfile == 0)
1683 pfatal_with_name (rf);
1684
1685 for (i=1; argv[i]; i++)
1686 {
1687 char *cp;
1688 for (cp = argv[i]; *cp; cp++)
1689 {
1690 if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
1691 fputc ('\\', argfile);
1692 fputc (*cp, argfile);
1693 }
1694 fputc ('\n', argfile);
1695 }
1696 fclose (argfile);
1697
1698 i = system (scmd);
1699
1700 remove (rf);
1701
1702 if (i == -1)
1703 {
1704 perror (program);
1705 return MIN_FATAL_STATUS << 8;
1706 }
1707
1708 return i << 8;
1709 }
1710
1711 #else /* not __MSDOS__ */
1712
1713 static int
1714 pexecute (program, argv)
1715 char *program;
1716 char *argv[];
1717 {
1718 int pid;
1719 int retries, sleep_interval;
1720
1721 /* Fork a subprocess; wait and retry if it fails. */
1722 sleep_interval = 1;
1723 for (retries = 0; retries < 4; retries++)
1724 {
1725 pid = vfork ();
1726 if (pid >= 0)
1727 break;
1728 sleep (sleep_interval);
1729 sleep_interval *= 2;
1730 }
1731
1732 switch (pid)
1733 {
1734 case -1:
1735 #ifdef vfork
1736 perror ("fork");
1737 #else
1738 perror ("vfork");
1739 #endif
1740 exit (1);
1741 /* NOTREACHED */
1742 return 0;
1743
1744 case 0: /* child */
1745 /* Exec the program. */
1746 execvp (program, argv);
1747 perror (program);
1748 exit (1);
1749 /* NOTREACHED */
1750 return 0;
1751
1752 default:
1753 /* Return child's process number. */
1754 return pid;
1755 }
1756 }
1757
1758 #endif /* not __MSDOS__ */
1759 #else /* not OS2 */
1760
1761 static int
1762 pexecute (program, argv)
1763 char *program;
1764 char *argv[];
1765 {
1766 return spawnvp (1, program, argv);
1767 }
1768 #endif /* not OS2 */
This page took 0.071073 seconds and 5 git commands to generate.