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