db3a9677eb15d04d57f47c0b83897f94964cdb7a
[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 "libiberty.h"
40 #include "sysdep.h"
41 #include "bucomm.h"
42 /* Internal BFD NLM header. */
43 #include "libnlm.h"
44 #include "nlmconv.h"
45
46 /* Needed for Alpha support. */
47 #include "coff/sym.h"
48 #include "coff/ecoff.h"
49
50 /* If strerror is just a macro, we want to use the one from libiberty
51 since it will handle undefined values. */
52 #undef strerror
53 extern char *strerror ();
54
55 #ifndef localtime
56 extern struct tm *localtime ();
57 #endif
58
59 #ifndef getenv
60 extern char *getenv ();
61 #endif
62
63 #ifndef SEEK_SET
64 #define SEEK_SET 0
65 #endif
66
67 #ifndef R_OK
68 #define R_OK 4
69 #define W_OK 2
70 #define X_OK 1
71 #endif
72 \f
73 /* Global variables. */
74
75 /* The name used to invoke the program. */
76 char *program_name;
77
78 /* The version number. */
79 extern char *program_version;
80
81 /* Local variables. */
82
83 /* Whether to print out debugging information (currently just controls
84 whether it prints the linker command if there is one). */
85 static int debug;
86
87 /* The symbol table. */
88 static asymbol **symbols;
89
90 /* A section we create in the output file to hold pointers to where
91 the sections of the input file end up. We will put a pointer to
92 this section in the NLM header. These is an entry for each input
93 section. The format is
94 null terminated section name
95 zeroes to adjust to 4 byte boundary
96 4 byte section data file pointer
97 4 byte section size
98 We don't need a version number. The way we find this information
99 is by finding a stamp in the NLM header information. If we need to
100 change the format of this information, we can simply change the
101 stamp. */
102 static asection *secsec;
103
104 /* A temporary file name to be unlinked on exit. Actually, for most
105 errors, we leave it around. It's not clear whether that is helpful
106 or not. */
107 static char *unlink_on_exit;
108
109 /* The list of long options. */
110 static struct option long_options[] =
111 {
112 { "debug", no_argument, 0, 'd' },
113 { "header-file", required_argument, 0, 'T' },
114 { "help", no_argument, 0, 'h' },
115 { "input-target", required_argument, 0, 'I' },
116 { "input-format", required_argument, 0, 'I' }, /* Obsolete */
117 { "linker", required_argument, 0, 'l' },
118 { "output-target", required_argument, 0, 'O' },
119 { "output-format", required_argument, 0, 'O' }, /* Obsolete */
120 { "version", no_argument, 0, 'V' },
121 { NULL, no_argument, 0, 0 }
122 };
123
124 /* Local routines. */
125
126 static void show_help PARAMS ((void));
127 static void show_usage PARAMS ((FILE *, int));
128 static const char *select_output_format PARAMS ((enum bfd_architecture,
129 unsigned long, boolean));
130 static void setup_sections PARAMS ((bfd *, asection *, PTR));
131 static void copy_sections PARAMS ((bfd *, asection *, PTR));
132 static void mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
133 long *, char *,
134 bfd_size_type));
135 static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
136 long *, char *,
137 bfd_size_type));
138 static void alpha_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
139 long *, char *,
140 bfd_size_type));
141 /* start-sanitize-powerpc-netware */
142 static void powerpc_build_stubs PARAMS ((bfd *, bfd *, asymbol ***, long *));
143 static void powerpc_resolve_stubs PARAMS ((bfd *, bfd *));
144 static void powerpc_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
145 long *, char *,
146 bfd_size_type));
147 /* end-sanitize-powerpc-netware */
148 static void default_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
149 long *, char *,
150 bfd_size_type));
151 static char *link_inputs PARAMS ((struct string_list *, char *));
152 static const char *choose_temp_base_try PARAMS ((const char *,
153 const char *));
154 static void choose_temp_base PARAMS ((void));
155 static int pexecute PARAMS ((char *, char *[]));
156 \f
157 /* The main routine. */
158
159 int
160 main (argc, argv)
161 int argc;
162 char **argv;
163 {
164 int opt;
165 char *input_file = NULL;
166 const char *input_format = NULL;
167 const char *output_format = NULL;
168 const char *header_file = NULL;
169 char *ld_arg = NULL;
170 Nlm_Internal_Fixed_Header fixed_hdr_struct;
171 Nlm_Internal_Variable_Header var_hdr_struct;
172 Nlm_Internal_Version_Header version_hdr_struct;
173 Nlm_Internal_Copyright_Header copyright_hdr_struct;
174 Nlm_Internal_Extended_Header extended_hdr_struct;
175 bfd *inbfd;
176 bfd *outbfd;
177 asymbol **newsyms, **outsyms;
178 long symcount, newsymalloc, newsymcount;
179 long symsize;
180 asection *text_sec, *bss_sec, *data_sec;
181 bfd_vma vma;
182 bfd_size_type align;
183 asymbol *endsym;
184 long i;
185 char inlead, outlead;
186 boolean gotstart, gotexit, gotcheck;
187 struct stat st;
188 FILE *custom_data, *help_data, *message_data, *rpc_data, *shared_data;
189 size_t custom_size, help_size, message_size, module_size, rpc_size;
190 asection *custom_section, *help_section, *message_section, *module_section;
191 asection *rpc_section, *shared_section;
192 bfd *sharedbfd;
193 size_t shared_offset, shared_size;
194 Nlm_Internal_Fixed_Header sharedhdr;
195 int len;
196 char *modname;
197 char **matching;
198
199 program_name = argv[0];
200 xmalloc_set_program_name (program_name);
201
202 bfd_init ();
203
204 while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options,
205 (int *) NULL))
206 != EOF)
207 {
208 switch (opt)
209 {
210 case 'd':
211 debug = 1;
212 break;
213 case 'h':
214 show_help ();
215 /*NOTREACHED*/
216 case 'I':
217 input_format = optarg;
218 break;
219 case 'l':
220 ld_arg = optarg;
221 break;
222 case 'O':
223 output_format = optarg;
224 break;
225 case 'T':
226 header_file = optarg;
227 break;
228 case 'V':
229 printf ("GNU %s version %s\n", program_name, program_version);
230 exit (0);
231 /*NOTREACHED*/
232 case 0:
233 break;
234 default:
235 show_usage (stderr, 1);
236 /*NOTREACHED*/
237 }
238 }
239
240 /* The input and output files may be named on the command line. */
241 output_file = NULL;
242 if (optind < argc)
243 {
244 input_file = argv[optind];
245 ++optind;
246 if (optind < argc)
247 {
248 output_file = argv[optind];
249 ++optind;
250 if (optind < argc)
251 show_usage (stderr, 1);
252 if (strcmp (input_file, output_file) == 0)
253 {
254 fprintf (stderr,
255 "%s: input and output files must be different\n",
256 program_name);
257 exit (1);
258 }
259 }
260 }
261
262 /* Initialize the header information to default values. */
263 fixed_hdr = &fixed_hdr_struct;
264 memset ((PTR) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct);
265 var_hdr = &var_hdr_struct;
266 memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct);
267 version_hdr = &version_hdr_struct;
268 memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct);
269 copyright_hdr = &copyright_hdr_struct;
270 memset ((PTR) &copyright_hdr_struct, 0, sizeof copyright_hdr_struct);
271 extended_hdr = &extended_hdr_struct;
272 memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct);
273 check_procedure = NULL;
274 custom_file = NULL;
275 debug_info = false;
276 exit_procedure = "_Stop";
277 export_symbols = NULL;
278 map_file = NULL;
279 full_map = false;
280 help_file = NULL;
281 import_symbols = NULL;
282 message_file = NULL;
283 modules = NULL;
284 sharelib_file = NULL;
285 start_procedure = "_Prelude";
286 verbose = false;
287 rpc_file = NULL;
288
289 parse_errors = 0;
290
291 /* Parse the header file (if there is one). */
292 if (header_file != NULL)
293 {
294 if (! nlmlex_file (header_file)
295 || yyparse () != 0
296 || parse_errors != 0)
297 exit (1);
298 }
299
300 if (input_files != NULL)
301 {
302 if (input_file != NULL)
303 {
304 fprintf (stderr,
305 "%s: input file named both on command line and with INPUT\n",
306 program_name);
307 exit (1);
308 }
309 if (input_files->next == NULL)
310 input_file = input_files->string;
311 else
312 input_file = link_inputs (input_files, ld_arg);
313 }
314 else if (input_file == NULL)
315 {
316 fprintf (stderr, "%s: no input file\n", program_name);
317 show_usage (stderr, 1);
318 }
319
320 inbfd = bfd_openr (input_file, input_format);
321 if (inbfd == NULL)
322 bfd_fatal (input_file);
323
324 if (! bfd_check_format_matches (inbfd, bfd_object, &matching))
325 {
326 bfd_nonfatal (input_file);
327 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
328 {
329 list_matching_formats (matching);
330 free (matching);
331 }
332 exit (1);
333 }
334
335 if (output_format == NULL)
336 output_format = select_output_format (bfd_get_arch (inbfd),
337 bfd_get_mach (inbfd),
338 inbfd->xvec->byteorder_big_p);
339
340 assert (output_format != NULL);
341
342 /* Use the output file named on the command line if it exists.
343 Otherwise use the file named in the OUTPUT statement. */
344 if (output_file == NULL)
345 {
346 fprintf (stderr, "%s: no name for output file\n",
347 program_name);
348 show_usage (stderr, 1);
349 }
350
351 outbfd = bfd_openw (output_file, output_format);
352 if (outbfd == NULL)
353 bfd_fatal (output_file);
354 if (! bfd_set_format (outbfd, bfd_object))
355 bfd_fatal (output_file);
356
357 assert (bfd_get_flavour (outbfd) == bfd_target_nlm_flavour);
358
359 if (bfd_arch_get_compatible (inbfd, outbfd) == NULL)
360 fprintf (stderr,
361 "%s: warning:input and output formats are not compatible\n",
362 program_name);
363
364 /* Move the values read from the command file into outbfd. */
365 *nlm_fixed_header (outbfd) = fixed_hdr_struct;
366 *nlm_variable_header (outbfd) = var_hdr_struct;
367 *nlm_version_header (outbfd) = version_hdr_struct;
368 *nlm_copyright_header (outbfd) = copyright_hdr_struct;
369 *nlm_extended_header (outbfd) = extended_hdr_struct;
370
371 /* Start copying the input BFD to the output BFD. */
372 if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd)))
373 bfd_fatal (bfd_get_filename (outbfd));
374
375 symsize = bfd_get_symtab_upper_bound (inbfd);
376 if (symsize < 0)
377 bfd_fatal (input_file);
378 symbols = (asymbol **) xmalloc (symsize);
379 symcount = bfd_canonicalize_symtab (inbfd, symbols);
380 if (symcount < 0)
381 bfd_fatal (input_file);
382
383 /* Make sure we have a .bss section. */
384 bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME);
385 if (bss_sec == NULL)
386 {
387 bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME);
388 if (bss_sec == NULL
389 || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC)
390 || ! bfd_set_section_alignment (outbfd, bss_sec, 1))
391 bfd_fatal ("make .bss section");
392 }
393
394 /* We store the original section names in the .nlmsections section,
395 so that programs which understand it can resurrect the original
396 sections from the NLM. We will put a pointer to .nlmsections in
397 the NLM header area. */
398 secsec = bfd_make_section (outbfd, ".nlmsections");
399 if (secsec == NULL)
400 bfd_fatal ("make .nlmsections section");
401 if (! bfd_set_section_flags (outbfd, secsec, SEC_HAS_CONTENTS))
402 bfd_fatal ("set .nlmsections flags");
403 /* start-sanitize-powerpc-netware */
404
405 /* For PowerPC NetWare we need to build stubs for calls to undefined
406 symbols. Because each stub requires an entry in the TOC section
407 which must be at the same location as other entries in the TOC
408 section, we must do this before determining where the TOC section
409 goes in setup_sections. */
410 if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
411 powerpc_build_stubs (inbfd, outbfd, &symbols, &symcount);
412 /* end-sanitize-powerpc-netware */
413
414 /* Set up the sections. */
415 bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);
416
417 text_sec = bfd_get_section_by_name (outbfd, NLM_CODE_NAME);
418
419 /* The .bss section immediately follows the .data section. */
420 data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME);
421 if (data_sec != NULL)
422 {
423 bfd_size_type add;
424
425 vma = bfd_get_section_size_before_reloc (data_sec);
426 align = 1 << bss_sec->alignment_power;
427 add = ((vma + align - 1) &~ (align - 1)) - vma;
428 vma += add;
429 if (! bfd_set_section_vma (outbfd, bss_sec, vma))
430 bfd_fatal ("set .bss vma");
431 if (add != 0)
432 {
433 bfd_size_type data_size;
434
435 data_size = bfd_get_section_size_before_reloc (data_sec);
436 if (! bfd_set_section_size (outbfd, data_sec, data_size + add))
437 bfd_fatal ("set .data size");
438 }
439 }
440
441 /* Adjust symbol information. */
442 inlead = bfd_get_symbol_leading_char (inbfd);
443 outlead = bfd_get_symbol_leading_char (outbfd);
444 gotstart = false;
445 gotexit = false;
446 gotcheck = false;
447 newsymalloc = 10;
448 newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *));
449 newsymcount = 0;
450 endsym = NULL;
451 for (i = 0; i < symcount; i++)
452 {
453 register asymbol *sym;
454
455 sym = symbols[i];
456
457 /* Add or remove a leading underscore. */
458 if (inlead != outlead)
459 {
460 if (inlead != '\0')
461 {
462 if (bfd_asymbol_name (sym)[0] == inlead)
463 {
464 if (outlead == '\0')
465 ++sym->name;
466 else
467 {
468 char *new;
469
470 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1);
471 new[0] = outlead;
472 strcpy (new + 1, bfd_asymbol_name (sym) + 1);
473 sym->name = new;
474 }
475 }
476 }
477 else
478 {
479 char *new;
480
481 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2);
482 new[0] = outlead;
483 strcpy (new + 1, bfd_asymbol_name (sym));
484 sym->name = new;
485 }
486 }
487
488 /* NLM's have an uninitialized data section, but they do not
489 have a common section in the Unix sense. Move all common
490 symbols into the .bss section, and mark them as exported. */
491 if (bfd_is_com_section (bfd_get_section (sym)))
492 {
493 bfd_vma size;
494
495 sym->section = bss_sec;
496 size = sym->value;
497 sym->value = bss_sec->_raw_size;
498 bss_sec->_raw_size += size;
499 align = 1 << bss_sec->alignment_power;
500 bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1);
501 sym->flags |= BSF_EXPORT | BSF_GLOBAL;
502 }
503 else if (bfd_get_section (sym)->output_section != NULL)
504 {
505 /* Move the symbol into the output section. */
506 sym->value += bfd_get_section (sym)->output_offset;
507 sym->section = bfd_get_section (sym)->output_section;
508 /* This is no longer a section symbol. */
509 sym->flags &=~ BSF_SECTION_SYM;
510 }
511
512 /* Force _edata and _end to be defined. This would normally be
513 done by the linker, but the manipulation of the common
514 symbols will confuse it. */
515 if ((sym->flags & BSF_DEBUGGING) == 0
516 && bfd_asymbol_name (sym)[0] == '_'
517 && bfd_get_section (sym) == &bfd_und_section)
518 {
519 if (strcmp (bfd_asymbol_name (sym), "_edata") == 0)
520 {
521 sym->section = bss_sec;
522 sym->value = 0;
523 }
524 if (strcmp (bfd_asymbol_name (sym), "_end") == 0)
525 {
526 sym->section = bss_sec;
527 endsym = sym;
528 }
529 /* start-sanitize-powerpc-netware */
530 /* For PowerPC NetWare, we define __GOT0. This is the start
531 of the .got section. */
532 if (bfd_get_arch (inbfd) == bfd_arch_powerpc
533 && strcmp (bfd_asymbol_name (sym), "__GOT0") == 0)
534 {
535 asection *got_sec;
536
537 got_sec = bfd_get_section_by_name (inbfd, ".got");
538 assert (got_sec != (asection *) NULL);
539 sym->value = got_sec->output_offset;
540 sym->section = got_sec->output_section;
541 }
542 /* end-sanitize-powerpc-netware */
543 }
544
545 /* If this is a global symbol, check the export list. */
546 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0)
547 {
548 register struct string_list *l;
549 int found_simple;
550
551 /* Unfortunately, a symbol can appear multiple times on the
552 export list, with and without prefixes. */
553 found_simple = 0;
554 for (l = export_symbols; l != NULL; l = l->next)
555 {
556 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
557 found_simple = 1;
558 else
559 {
560 char *zbase;
561
562 zbase = strchr (l->string, '@');
563 if (zbase != NULL
564 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
565 {
566 /* We must add a symbol with this prefix. */
567 if (newsymcount >= newsymalloc)
568 {
569 newsymalloc += 10;
570 newsyms = ((asymbol **)
571 xrealloc ((PTR) newsyms,
572 (newsymalloc
573 * sizeof (asymbol *))));
574 }
575 newsyms[newsymcount] =
576 (asymbol *) xmalloc (sizeof (asymbol));
577 *newsyms[newsymcount] = *sym;
578 newsyms[newsymcount]->name = l->string;
579 ++newsymcount;
580 }
581 }
582 }
583 if (! found_simple)
584 {
585 /* The unmodified symbol is actually not exported at
586 all. */
587 sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT);
588 sym->flags |= BSF_LOCAL;
589 }
590 }
591
592 /* If it's an undefined symbol, see if it's on the import list.
593 Change the prefix if necessary. */
594 if (bfd_get_section (sym) == &bfd_und_section)
595 {
596 register struct string_list *l;
597
598 for (l = import_symbols; l != NULL; l = l->next)
599 {
600 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
601 break;
602 else
603 {
604 char *zbase;
605
606 zbase = strchr (l->string, '@');
607 if (zbase != NULL
608 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
609 {
610 sym->name = l->string;
611 break;
612 }
613 }
614 }
615 if (l == NULL)
616 fprintf (stderr,
617 "%s: warning: symbol %s imported but not in import list\n",
618 program_name, bfd_asymbol_name (sym));
619 }
620
621 /* See if it's one of the special named symbols. */
622 if ((sym->flags & BSF_DEBUGGING) == 0)
623 {
624 bfd_vma val;
625
626 /* FIXME: If these symbols are not in the .text section, we
627 add the .text section size to the value. This may not be
628 correct for all targets. I'm not sure how this should
629 really be handled. */
630 if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0)
631 {
632 val = bfd_asymbol_value (sym);
633 if (bfd_get_section (sym) == data_sec
634 && text_sec != (asection *) NULL)
635 val += bfd_section_size (outbfd, text_sec);
636 if (! bfd_set_start_address (outbfd, val))
637 bfd_fatal ("set start address");
638 gotstart = true;
639 }
640 if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0)
641 {
642 val = bfd_asymbol_value (sym);
643 if (bfd_get_section (sym) == data_sec
644 && text_sec != (asection *) NULL)
645 val += bfd_section_size (outbfd, text_sec);
646 nlm_fixed_header (outbfd)->exitProcedureOffset = val;
647 gotexit = true;
648 }
649 if (check_procedure != NULL
650 && strcmp (bfd_asymbol_name (sym), check_procedure) == 0)
651 {
652 val = bfd_asymbol_value (sym);
653 if (bfd_get_section (sym) == data_sec
654 && text_sec != (asection *) NULL)
655 val += bfd_section_size (outbfd, text_sec);
656 nlm_fixed_header (outbfd)->checkUnloadProcedureOffset = val;
657 gotcheck = true;
658 }
659 }
660 }
661
662 if (endsym != NULL)
663 {
664 endsym->value = bfd_get_section_size_before_reloc (bss_sec);
665
666 /* FIXME: If any relocs referring to _end use inplace addends,
667 then I think they need to be updated. This is handled by
668 i386_mangle_relocs. Is it needed for any other object
669 formats? */
670 }
671
672 if (newsymcount == 0)
673 outsyms = symbols;
674 else
675 {
676 outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1)
677 * sizeof (asymbol *));
678 memcpy (outsyms, symbols, symcount * sizeof (asymbol *));
679 memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *));
680 outsyms[symcount + newsymcount] = NULL;
681 }
682
683 bfd_set_symtab (outbfd, outsyms, symcount + newsymcount);
684
685 if (! gotstart)
686 fprintf (stderr, "%s: warning: START procedure %s not defined\n",
687 program_name, start_procedure);
688 if (! gotexit)
689 fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n",
690 program_name, exit_procedure);
691 if (check_procedure != NULL
692 && ! gotcheck)
693 fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n",
694 program_name, check_procedure);
695
696 /* Add additional sections required for the header information. */
697 if (custom_file != NULL)
698 {
699 custom_data = fopen (custom_file, "r");
700 if (custom_data == NULL
701 || fstat (fileno (custom_data), &st) < 0)
702 {
703 fprintf (stderr, "%s:%s: %s\n", program_name, custom_file,
704 strerror (errno));
705 custom_file = NULL;
706 }
707 else
708 {
709 custom_size = st.st_size;
710 custom_section = bfd_make_section (outbfd, ".nlmcustom");
711 if (custom_section == NULL
712 || ! bfd_set_section_size (outbfd, custom_section, custom_size)
713 || ! bfd_set_section_flags (outbfd, custom_section,
714 SEC_HAS_CONTENTS))
715 bfd_fatal ("custom section");
716 }
717 }
718 if (help_file != NULL)
719 {
720 help_data = fopen (help_file, "r");
721 if (help_data == NULL
722 || fstat (fileno (help_data), &st) < 0)
723 {
724 fprintf (stderr, "%s:%s: %s\n", program_name, help_file,
725 strerror (errno));
726 help_file = NULL;
727 }
728 else
729 {
730 help_size = st.st_size;
731 help_section = bfd_make_section (outbfd, ".nlmhelp");
732 if (help_section == NULL
733 || ! bfd_set_section_size (outbfd, help_section, help_size)
734 || ! bfd_set_section_flags (outbfd, help_section,
735 SEC_HAS_CONTENTS))
736 bfd_fatal ("help section");
737 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
738 }
739 }
740 if (message_file != NULL)
741 {
742 message_data = fopen (message_file, "r");
743 if (message_data == NULL
744 || fstat (fileno (message_data), &st) < 0)
745 {
746 fprintf (stderr, "%s:%s: %s\n", program_name, message_file,
747 strerror (errno));
748 message_file = NULL;
749 }
750 else
751 {
752 message_size = st.st_size;
753 message_section = bfd_make_section (outbfd, ".nlmmessages");
754 if (message_section == NULL
755 || ! bfd_set_section_size (outbfd, message_section, message_size)
756 || ! bfd_set_section_flags (outbfd, message_section,
757 SEC_HAS_CONTENTS))
758 bfd_fatal ("message section");
759 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
760 }
761 }
762 if (modules != NULL)
763 {
764 struct string_list *l;
765
766 module_size = 0;
767 for (l = modules; l != NULL; l = l->next)
768 module_size += strlen (l->string) + 1;
769 module_section = bfd_make_section (outbfd, ".nlmmodules");
770 if (module_section == NULL
771 || ! bfd_set_section_size (outbfd, module_section, module_size)
772 || ! bfd_set_section_flags (outbfd, module_section,
773 SEC_HAS_CONTENTS))
774 bfd_fatal ("module section");
775 }
776 if (rpc_file != NULL)
777 {
778 rpc_data = fopen (rpc_file, "r");
779 if (rpc_data == NULL
780 || fstat (fileno (rpc_data), &st) < 0)
781 {
782 fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file,
783 strerror (errno));
784 rpc_file = NULL;
785 }
786 else
787 {
788 rpc_size = st.st_size;
789 rpc_section = bfd_make_section (outbfd, ".nlmrpc");
790 if (rpc_section == NULL
791 || ! bfd_set_section_size (outbfd, rpc_section, rpc_size)
792 || ! bfd_set_section_flags (outbfd, rpc_section,
793 SEC_HAS_CONTENTS))
794 bfd_fatal ("rpc section");
795 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
796 }
797 }
798 if (sharelib_file != NULL)
799 {
800 sharedbfd = bfd_openr (sharelib_file, output_format);
801 if (sharedbfd == NULL
802 || ! bfd_check_format (sharedbfd, bfd_object))
803 {
804 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
805 bfd_errmsg (bfd_get_error ()));
806 sharelib_file = NULL;
807 }
808 else
809 {
810 sharedhdr = *nlm_fixed_header (sharedbfd);
811 bfd_close (sharedbfd);
812 shared_data = fopen (sharelib_file, "r");
813 if (shared_data == NULL
814 || (fstat (fileno (shared_data), &st) < 0))
815 {
816 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
817 strerror (errno));
818 sharelib_file = NULL;
819 }
820 else
821 {
822 /* If we were clever, we could just copy out the
823 sections of the shared library which we actually
824 need. However, we would have to figure out the sizes
825 of the external and public information, and that can
826 not be done without reading through them. */
827 if (sharedhdr.uninitializedDataSize > 0)
828 {
829 /* There is no place to record this information. */
830 fprintf (stderr,
831 "%s:%s: warning: shared libraries can not have uninitialized data\n",
832 program_name, sharelib_file);
833 }
834 shared_offset = st.st_size;
835 if (shared_offset > sharedhdr.codeImageOffset)
836 shared_offset = sharedhdr.codeImageOffset;
837 if (shared_offset > sharedhdr.dataImageOffset)
838 shared_offset = sharedhdr.dataImageOffset;
839 if (shared_offset > sharedhdr.relocationFixupOffset)
840 shared_offset = sharedhdr.relocationFixupOffset;
841 if (shared_offset > sharedhdr.externalReferencesOffset)
842 shared_offset = sharedhdr.externalReferencesOffset;
843 if (shared_offset > sharedhdr.publicsOffset)
844 shared_offset = sharedhdr.publicsOffset;
845 shared_size = st.st_size - shared_offset;
846 shared_section = bfd_make_section (outbfd, ".nlmshared");
847 if (shared_section == NULL
848 || ! bfd_set_section_size (outbfd, shared_section,
849 shared_size)
850 || ! bfd_set_section_flags (outbfd, shared_section,
851 SEC_HAS_CONTENTS))
852 bfd_fatal ("shared section");
853 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
854 }
855 }
856 }
857
858 /* Check whether a version was given. */
859 if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0)
860 fprintf (stderr, "%s: warning: No version number given\n",
861 program_name);
862
863 /* At least for now, always create an extended header, because that
864 is what NLMLINK does. */
865 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
866
867 strncpy (nlm_cygnus_ext_header (outbfd)->stamp, "CyGnUsEx", 8);
868
869 /* If the date was not given, force it in. */
870 if (nlm_version_header (outbfd)->month == 0
871 && nlm_version_header (outbfd)->day == 0
872 && nlm_version_header (outbfd)->year == 0)
873 {
874 time_t now;
875 struct tm *ptm;
876
877 time (&now);
878 ptm = localtime (&now);
879 nlm_version_header (outbfd)->month = ptm->tm_mon + 1;
880 nlm_version_header (outbfd)->day = ptm->tm_mday;
881 nlm_version_header (outbfd)->year = ptm->tm_year + 1900;
882 strncpy (version_hdr->stamp, "VeRsIoN#", 8);
883 }
884 /* start-sanitize-powerpc-netware */
885
886 /* Resolve the stubs we build for PowerPC NetWare. */
887 if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
888 powerpc_resolve_stubs (inbfd, outbfd);
889 /* end-sanitize-powerpc-netware */
890
891 /* Copy over the sections. */
892 bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd);
893
894 /* Finish up the header information. */
895 if (custom_file != NULL)
896 {
897 PTR data;
898
899 data = xmalloc (custom_size);
900 if (fread (data, 1, custom_size, custom_data) != custom_size)
901 fprintf (stderr, "%s:%s: read: %s\n", program_name, custom_file,
902 strerror (errno));
903 else
904 {
905 if (! bfd_set_section_contents (outbfd, custom_section, data,
906 (file_ptr) 0, custom_size))
907 bfd_fatal ("custom section");
908 nlm_fixed_header (outbfd)->customDataOffset =
909 custom_section->filepos;
910 nlm_fixed_header (outbfd)->customDataSize = custom_size;
911 }
912 free (data);
913 }
914 if (! debug_info)
915 {
916 /* As a special hack, the backend recognizes a debugInfoOffset
917 of -1 to mean that it should not output any debugging
918 information. This can not be handling by fiddling with the
919 symbol table because exported symbols appear in both the
920 export information and the debugging information. */
921 nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1;
922 }
923 if (map_file != NULL)
924 fprintf (stderr,
925 "%s: warning: MAP and FULLMAP are not supported; try ld -M\n",
926 program_name);
927 if (help_file != NULL)
928 {
929 PTR data;
930
931 data = xmalloc (help_size);
932 if (fread (data, 1, help_size, help_data) != help_size)
933 fprintf (stderr, "%s:%s: read: %s\n", program_name, help_file,
934 strerror (errno));
935 else
936 {
937 if (! bfd_set_section_contents (outbfd, help_section, data,
938 (file_ptr) 0, help_size))
939 bfd_fatal ("help section");
940 nlm_extended_header (outbfd)->helpFileOffset =
941 help_section->filepos;
942 nlm_extended_header (outbfd)->helpFileLength = help_size;
943 }
944 free (data);
945 }
946 if (message_file != NULL)
947 {
948 PTR data;
949
950 data = xmalloc (message_size);
951 if (fread (data, 1, message_size, message_data) != message_size)
952 fprintf (stderr, "%s:%s: read: %s\n", program_name, message_file,
953 strerror (errno));
954 else
955 {
956 if (! bfd_set_section_contents (outbfd, message_section, data,
957 (file_ptr) 0, message_size))
958 bfd_fatal ("message section");
959 nlm_extended_header (outbfd)->messageFileOffset =
960 message_section->filepos;
961 nlm_extended_header (outbfd)->messageFileLength = message_size;
962
963 /* FIXME: Are these offsets correct on all platforms? Are
964 they 32 bits on all platforms? What endianness? */
965 nlm_extended_header (outbfd)->languageID =
966 bfd_h_get_32 (outbfd, (bfd_byte *) data + 106);
967 nlm_extended_header (outbfd)->messageCount =
968 bfd_h_get_32 (outbfd, (bfd_byte *) data + 110);
969 }
970 free (data);
971 }
972 if (modules != NULL)
973 {
974 PTR data;
975 unsigned char *set;
976 struct string_list *l;
977 bfd_size_type c;
978
979 data = xmalloc (module_size);
980 c = 0;
981 set = (unsigned char *) data;
982 for (l = modules; l != NULL; l = l->next)
983 {
984 *set = strlen (l->string);
985 strncpy (set + 1, l->string, *set);
986 set += *set + 1;
987 ++c;
988 }
989 if (! bfd_set_section_contents (outbfd, module_section, data,
990 (file_ptr) 0, module_size))
991 bfd_fatal ("module section");
992 nlm_fixed_header (outbfd)->moduleDependencyOffset =
993 module_section->filepos;
994 nlm_fixed_header (outbfd)->numberOfModuleDependencies = c;
995 }
996 if (rpc_file != NULL)
997 {
998 PTR data;
999
1000 data = xmalloc (rpc_size);
1001 if (fread (data, 1, rpc_size, rpc_data) != rpc_size)
1002 fprintf (stderr, "%s:%s: read: %s\n", program_name, rpc_file,
1003 strerror (errno));
1004 else
1005 {
1006 if (! bfd_set_section_contents (outbfd, rpc_section, data,
1007 (file_ptr) 0, rpc_size))
1008 bfd_fatal ("rpc section");
1009 nlm_extended_header (outbfd)->RPCDataOffset =
1010 rpc_section->filepos;
1011 nlm_extended_header (outbfd)->RPCDataLength = rpc_size;
1012 }
1013 free (data);
1014 }
1015 if (sharelib_file != NULL)
1016 {
1017 PTR data;
1018
1019 data = xmalloc (shared_size);
1020 if (fseek (shared_data, shared_offset, SEEK_SET) != 0
1021 || fread (data, 1, shared_size, shared_data) != shared_size)
1022 fprintf (stderr, "%s:%s: read: %s\n", program_name, sharelib_file,
1023 strerror (errno));
1024 else
1025 {
1026 if (! bfd_set_section_contents (outbfd, shared_section, data,
1027 (file_ptr) 0, shared_size))
1028 bfd_fatal ("shared section");
1029 }
1030 nlm_extended_header (outbfd)->sharedCodeOffset =
1031 sharedhdr.codeImageOffset - shared_offset + shared_section->filepos;
1032 nlm_extended_header (outbfd)->sharedCodeLength =
1033 sharedhdr.codeImageSize;
1034 nlm_extended_header (outbfd)->sharedDataOffset =
1035 sharedhdr.dataImageOffset - shared_offset + shared_section->filepos;
1036 nlm_extended_header (outbfd)->sharedDataLength =
1037 sharedhdr.dataImageSize;
1038 nlm_extended_header (outbfd)->sharedRelocationFixupOffset =
1039 (sharedhdr.relocationFixupOffset
1040 - shared_offset
1041 + shared_section->filepos);
1042 nlm_extended_header (outbfd)->sharedRelocationFixupCount =
1043 sharedhdr.numberOfRelocationFixups;
1044 nlm_extended_header (outbfd)->sharedExternalReferenceOffset =
1045 (sharedhdr.externalReferencesOffset
1046 - shared_offset
1047 + shared_section->filepos);
1048 nlm_extended_header (outbfd)->sharedExternalReferenceCount =
1049 sharedhdr.numberOfExternalReferences;
1050 nlm_extended_header (outbfd)->sharedPublicsOffset =
1051 sharedhdr.publicsOffset - shared_offset + shared_section->filepos;
1052 nlm_extended_header (outbfd)->sharedPublicsCount =
1053 sharedhdr.numberOfPublics;
1054 nlm_extended_header (outbfd)->sharedDebugRecordOffset =
1055 sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos;
1056 nlm_extended_header (outbfd)->sharedDebugRecordCount =
1057 sharedhdr.numberOfDebugRecords;
1058 nlm_extended_header (outbfd)->SharedInitializationOffset =
1059 sharedhdr.codeStartOffset;
1060 nlm_extended_header (outbfd)->SharedExitProcedureOffset =
1061 sharedhdr.exitProcedureOffset;
1062 free (data);
1063 }
1064 len = strlen (output_file);
1065 if (len > NLM_MODULE_NAME_SIZE - 2)
1066 len = NLM_MODULE_NAME_SIZE - 2;
1067 nlm_fixed_header (outbfd)->moduleName[0] = len;
1068
1069 strncpy (nlm_fixed_header (outbfd)->moduleName + 1, output_file,
1070 NLM_MODULE_NAME_SIZE - 2);
1071 nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0';
1072 for (modname = nlm_fixed_header (outbfd)->moduleName;
1073 *modname != '\0';
1074 modname++)
1075 if (islower (*modname))
1076 *modname = toupper (*modname);
1077
1078 strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
1079 NLM_OLD_THREAD_NAME_LENGTH);
1080
1081 nlm_cygnus_ext_header (outbfd)->offset = secsec->filepos;
1082 nlm_cygnus_ext_header (outbfd)->length = bfd_section_size (outbfd, secsec);
1083
1084 if (! bfd_close (outbfd))
1085 bfd_fatal (output_file);
1086 if (! bfd_close (inbfd))
1087 bfd_fatal (input_file);
1088
1089 if (unlink_on_exit != NULL)
1090 unlink (unlink_on_exit);
1091
1092 return 0;
1093 }
1094 \f
1095 /* Display a help message and exit. */
1096
1097 static void
1098 show_help ()
1099 {
1100 printf ("%s: Convert an object file into a NetWare Loadable Module\n",
1101 program_name);
1102 show_usage (stdout, 0);
1103 }
1104
1105 /* Show a usage message and exit. */
1106
1107 static void
1108 show_usage (file, status)
1109 FILE *file;
1110 int status;
1111 {
1112 fprintf (file, "\
1113 Usage: %s [-dhV] [-I bfdname] [-O bfdname] [-T header-file] [-l linker]\n\
1114 [--input-target=bfdname] [--output-target=bfdname]\n\
1115 [--header-file=file] [--linker=linker] [--debug]\n\
1116 [--help] [--version]\n\
1117 [in-file [out-file]]\n",
1118 program_name);
1119 exit (status);
1120 }
1121 \f
1122 /* Select the output format based on the input architecture, machine,
1123 and endianness. This chooses the appropriate NLM target. */
1124
1125 static const char *
1126 select_output_format (arch, mach, bigendian)
1127 enum bfd_architecture arch;
1128 unsigned long mach;
1129 boolean bigendian;
1130 {
1131 switch (arch)
1132 {
1133 case bfd_arch_i386:
1134 return "nlm32-i386";
1135 case bfd_arch_sparc:
1136 return "nlm32-sparc";
1137 case bfd_arch_alpha:
1138 return "nlm32-alpha";
1139 /* start-sanitize-powerpc-netware */
1140 case bfd_arch_powerpc:
1141 return "nlm32-powerpc";
1142 /* end-sanitize-powerpc-netware */
1143 default:
1144 fprintf (stderr, "%s: no default NLM format for %s\n",
1145 program_name, bfd_printable_arch_mach (arch, mach));
1146 exit (1);
1147 /* Avoid warning. */
1148 return NULL;
1149 }
1150 /*NOTREACHED*/
1151 }
1152 \f
1153 /* The BFD sections are copied in two passes. This function selects
1154 the output section for each input section, and sets up the section
1155 name, size, etc. */
1156
1157 static void
1158 setup_sections (inbfd, insec, data_ptr)
1159 bfd *inbfd;
1160 asection *insec;
1161 PTR data_ptr;
1162 {
1163 bfd *outbfd = (bfd *) data_ptr;
1164 flagword f;
1165 const char *outname;
1166 asection *outsec;
1167 bfd_vma offset;
1168 bfd_size_type align;
1169 bfd_size_type add;
1170 bfd_size_type secsecsize;
1171
1172 f = bfd_get_section_flags (inbfd, insec);
1173 if (f & SEC_CODE)
1174 outname = NLM_CODE_NAME;
1175 else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS))
1176 outname = NLM_INITIALIZED_DATA_NAME;
1177 else if (f & SEC_ALLOC)
1178 outname = NLM_UNINITIALIZED_DATA_NAME;
1179 else
1180 outname = bfd_section_name (inbfd, insec);
1181
1182 outsec = bfd_get_section_by_name (outbfd, outname);
1183 if (outsec == NULL)
1184 {
1185 outsec = bfd_make_section (outbfd, outname);
1186 if (outsec == NULL)
1187 bfd_fatal ("make section");
1188 }
1189
1190 insec->output_section = outsec;
1191
1192 offset = bfd_section_size (outbfd, outsec);
1193 align = 1 << bfd_section_alignment (inbfd, insec);
1194 add = ((offset + align - 1) &~ (align - 1)) - offset;
1195 insec->output_offset = offset + add;
1196
1197 if (! bfd_set_section_size (outbfd, outsec,
1198 (bfd_section_size (outbfd, outsec)
1199 + bfd_section_size (inbfd, insec)
1200 + add)))
1201 bfd_fatal ("set section size");
1202
1203 if ((bfd_section_alignment (inbfd, insec)
1204 > bfd_section_alignment (outbfd, outsec))
1205 && ! bfd_set_section_alignment (outbfd, outsec,
1206 bfd_section_alignment (inbfd, insec)))
1207 bfd_fatal ("set section alignment");
1208
1209 if (! bfd_set_section_flags (outbfd, outsec, f))
1210 bfd_fatal ("set section flags");
1211
1212 bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
1213
1214 /* For each input section we allocate space for an entry in
1215 .nlmsections. */
1216 secsecsize = bfd_section_size (outbfd, secsec);
1217 secsecsize += strlen (bfd_section_name (inbfd, insec)) + 1;
1218 secsecsize = (secsecsize + 3) &~ 3;
1219 secsecsize += 8;
1220 if (! bfd_set_section_size (outbfd, secsec, secsecsize))
1221 bfd_fatal ("set .nlmsections size");
1222 }
1223
1224 /* Copy the section contents. */
1225
1226 static void
1227 copy_sections (inbfd, insec, data_ptr)
1228 bfd *inbfd;
1229 asection *insec;
1230 PTR data_ptr;
1231 {
1232 static bfd_size_type secsecoff = 0;
1233 bfd *outbfd = (bfd *) data_ptr;
1234 const char *inname;
1235 asection *outsec;
1236 bfd_size_type size;
1237 PTR contents;
1238 long reloc_size;
1239 bfd_byte buf[4];
1240 bfd_size_type add;
1241
1242 inname = bfd_section_name (inbfd, insec);
1243
1244 outsec = insec->output_section;
1245 assert (outsec != NULL);
1246
1247 size = bfd_get_section_size_before_reloc (insec);
1248
1249 /* FIXME: Why are these necessary? */
1250 insec->_cooked_size = insec->_raw_size;
1251 insec->reloc_done = true;
1252
1253 if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
1254 contents = NULL;
1255 else
1256 {
1257 contents = xmalloc (size);
1258 if (! bfd_get_section_contents (inbfd, insec, contents,
1259 (file_ptr) 0, size))
1260 bfd_fatal (bfd_get_filename (inbfd));
1261 }
1262
1263 reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
1264 if (reloc_size < 0)
1265 bfd_fatal (bfd_get_filename (inbfd));
1266 if (reloc_size != 0)
1267 {
1268 arelent **relocs;
1269 long reloc_count;
1270
1271 relocs = (arelent **) xmalloc (reloc_size);
1272 reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols);
1273 if (reloc_count < 0)
1274 bfd_fatal (bfd_get_filename (inbfd));
1275 mangle_relocs (outbfd, insec, &relocs, &reloc_count, (char *) contents,
1276 size);
1277
1278 /* FIXME: refers to internal BFD fields. */
1279 if (outsec->orelocation != (arelent **) NULL)
1280 {
1281 bfd_size_type total_count;
1282 arelent **combined;
1283
1284 total_count = reloc_count + outsec->reloc_count;
1285 combined = (arelent **) xmalloc (total_count * sizeof (arelent));
1286 memcpy (combined, outsec->orelocation,
1287 outsec->reloc_count * sizeof (arelent));
1288 memcpy (combined + outsec->reloc_count, relocs,
1289 (size_t) (reloc_count * sizeof (arelent)));
1290 free (outsec->orelocation);
1291 reloc_count = total_count;
1292 relocs = combined;
1293 }
1294
1295 bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
1296 }
1297
1298 if (contents != NULL)
1299 {
1300 if (! bfd_set_section_contents (outbfd, outsec, contents,
1301 insec->output_offset, size))
1302 bfd_fatal (bfd_get_filename (outbfd));
1303 free (contents);
1304 }
1305
1306 /* Add this section to .nlmsections. */
1307 if (! bfd_set_section_contents (outbfd, secsec, (PTR) inname, secsecoff,
1308 strlen (inname) + 1))
1309 bfd_fatal ("set .nlmsection contents");
1310 secsecoff += strlen (inname) + 1;
1311
1312 add = ((secsecoff + 3) &~ 3) - secsecoff;
1313 if (add != 0)
1314 {
1315 bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
1316 if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, add))
1317 bfd_fatal ("set .nlmsection contents");
1318 secsecoff += add;
1319 }
1320
1321 if (contents != NULL)
1322 bfd_h_put_32 (outbfd, (bfd_vma) outsec->filepos, buf);
1323 else
1324 bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
1325 if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
1326 bfd_fatal ("set .nlmsection contents");
1327 secsecoff += 4;
1328
1329 bfd_h_put_32 (outbfd, (bfd_vma) size, buf);
1330 if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
1331 bfd_fatal ("set .nlmsection contents");
1332 secsecoff += 4;
1333 }
1334
1335 /* Some, perhaps all, NetWare targets require changing the relocs used
1336 by the input formats. */
1337
1338 static void
1339 mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1340 contents_size)
1341 bfd *outbfd;
1342 asection *insec;
1343 arelent ***relocs_ptr;
1344 long *reloc_count_ptr;
1345 char *contents;
1346 bfd_size_type contents_size;
1347 {
1348 switch (bfd_get_arch (outbfd))
1349 {
1350 case bfd_arch_i386:
1351 i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1352 contents, contents_size);
1353 break;
1354 case bfd_arch_alpha:
1355 alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1356 contents, contents_size);
1357 break;
1358 /* start-sanitize-powerpc-netware */
1359 case bfd_arch_powerpc:
1360 powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1361 contents, contents_size);
1362 break;
1363 /* end-sanitize-powerpc-netware */
1364 default:
1365 default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1366 contents, contents_size);
1367 break;
1368 }
1369 }
1370
1371 /* By default all we need to do for relocs is change the address by
1372 the output_offset. */
1373
1374 /*ARGSUSED*/
1375 static void
1376 default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1377 contents_size)
1378 bfd *outbfd;
1379 asection *insec;
1380 arelent ***relocs_ptr;
1381 long *reloc_count_ptr;
1382 char *contents;
1383 bfd_size_type contents_size;
1384 {
1385 if (insec->output_offset != 0)
1386 {
1387 long reloc_count;
1388 register arelent **relocs;
1389 register long i;
1390
1391 reloc_count = *reloc_count_ptr;
1392 relocs = *relocs_ptr;
1393 for (i = 0; i < reloc_count; i++, relocs++)
1394 (*relocs)->address += insec->output_offset;
1395 }
1396 }
1397
1398 /* NetWare on the i386 supports a restricted set of relocs, which are
1399 different from those used on other i386 targets. This routine
1400 converts the relocs. It is, obviously, very target dependent. At
1401 the moment, the nlm32-i386 backend performs similar translations;
1402 however, it is more reliable and efficient to do them here. */
1403
1404 static reloc_howto_type nlm_i386_pcrel_howto =
1405 HOWTO (1, /* type */
1406 0, /* rightshift */
1407 2, /* size (0 = byte, 1 = short, 2 = long) */
1408 32, /* bitsize */
1409 true, /* pc_relative */
1410 0, /* bitpos */
1411 complain_overflow_signed, /* complain_on_overflow */
1412 0, /* special_function */
1413 "DISP32", /* name */
1414 true, /* partial_inplace */
1415 0xffffffff, /* src_mask */
1416 0xffffffff, /* dst_mask */
1417 true); /* pcrel_offset */
1418
1419 static void
1420 i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1421 contents_size)
1422 bfd *outbfd;
1423 asection *insec;
1424 arelent ***relocs_ptr;
1425 long *reloc_count_ptr;
1426 char *contents;
1427 bfd_size_type contents_size;
1428 {
1429 long reloc_count, i;
1430 arelent **relocs;
1431
1432 reloc_count = *reloc_count_ptr;
1433 relocs = *relocs_ptr;
1434 for (i = 0; i < reloc_count; i++)
1435 {
1436 arelent *rel;
1437 asymbol *sym;
1438 bfd_size_type address;
1439 bfd_vma addend;
1440
1441 rel = *relocs++;
1442 sym = *rel->sym_ptr_ptr;
1443
1444 /* We're moving the relocs from the input section to the output
1445 section, so we must adjust the address accordingly. */
1446 address = rel->address;
1447 rel->address += insec->output_offset;
1448
1449 /* Note that no serious harm will ensue if we fail to change a
1450 reloc. The backend will fail when writing out the reloc. */
1451
1452 /* Make sure this reloc is within the data we have. We use only
1453 4 byte relocs here, so we insist on having 4 bytes. */
1454 if (address + 4 > contents_size)
1455 continue;
1456
1457 /* A PC relative reloc entirely within a single section is
1458 completely unnecessary. This can be generated by ld -r. */
1459 if (sym == insec->symbol
1460 && rel->howto != NULL
1461 && rel->howto->pc_relative
1462 && ! rel->howto->pcrel_offset)
1463 {
1464 --*reloc_count_ptr;
1465 --relocs;
1466 memmove (relocs, relocs + 1,
1467 (size_t) ((reloc_count - i) * sizeof (arelent *)));
1468 continue;
1469 }
1470
1471 /* Get the amount the relocation will add in. */
1472 addend = rel->addend + sym->value;
1473
1474 /* NetWare doesn't support PC relative relocs against defined
1475 symbols, so we have to eliminate them by doing the relocation
1476 now. We can only do this if the reloc is within a single
1477 section. */
1478 if (rel->howto != NULL
1479 && rel->howto->pc_relative
1480 && bfd_get_section (sym) == insec->output_section)
1481 {
1482 bfd_vma val;
1483
1484 if (rel->howto->pcrel_offset)
1485 addend -= address;
1486
1487 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1488 val += addend;
1489 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1490
1491 --*reloc_count_ptr;
1492 --relocs;
1493 memmove (relocs, relocs + 1,
1494 (size_t) ((reloc_count - i) * sizeof (arelent *)));
1495 continue;
1496 }
1497
1498 /* NetWare doesn't support reloc addends, so we get rid of them
1499 here by simply adding them into the object data. We handle
1500 the symbol value, if any, the same way. */
1501 if (addend != 0
1502 && rel->howto != NULL
1503 && rel->howto->rightshift == 0
1504 && rel->howto->size == 2
1505 && rel->howto->bitsize == 32
1506 && rel->howto->bitpos == 0
1507 && rel->howto->src_mask == 0xffffffff
1508 && rel->howto->dst_mask == 0xffffffff)
1509 {
1510 bfd_vma val;
1511
1512 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1513 val += addend;
1514 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1515
1516 /* Adjust the reloc for the changes we just made. */
1517 rel->addend = 0;
1518 if (bfd_get_section (sym) != &bfd_und_section)
1519 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
1520 }
1521
1522 /* NetWare uses a reloc with pcrel_offset set. We adjust
1523 pc_relative relocs accordingly. We are going to change the
1524 howto field, so we can only do this if the current one is
1525 compatible. We should check that special_function is NULL
1526 here, but at the moment coff-i386 uses a special_function
1527 which does not affect what we are doing here. */
1528 if (rel->howto != NULL
1529 && rel->howto->pc_relative
1530 && ! rel->howto->pcrel_offset
1531 && rel->howto->rightshift == 0
1532 && rel->howto->size == 2
1533 && rel->howto->bitsize == 32
1534 && rel->howto->bitpos == 0
1535 && rel->howto->src_mask == 0xffffffff
1536 && rel->howto->dst_mask == 0xffffffff)
1537 {
1538 bfd_vma val;
1539
1540 /* When pcrel_offset is not set, it means that the negative
1541 of the address of the memory location is stored in the
1542 memory location. We must add it back in. */
1543 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1544 val += address;
1545 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1546
1547 /* We must change to a new howto. */
1548 rel->howto = &nlm_i386_pcrel_howto;
1549 }
1550 }
1551 }
1552
1553 /* On the Alpha the first reloc for every section must be a special
1554 relocs which hold the GP address. Also, the first reloc in the
1555 file must be a special reloc which holds the address of the .lita
1556 section. */
1557
1558 static reloc_howto_type nlm32_alpha_nw_howto =
1559 HOWTO (ALPHA_R_NW_RELOC, /* type */
1560 0, /* rightshift */
1561 0, /* size (0 = byte, 1 = short, 2 = long) */
1562 0, /* bitsize */
1563 false, /* pc_relative */
1564 0, /* bitpos */
1565 complain_overflow_dont, /* complain_on_overflow */
1566 0, /* special_function */
1567 "NW_RELOC", /* name */
1568 false, /* partial_inplace */
1569 0, /* src_mask */
1570 0, /* dst_mask */
1571 false); /* pcrel_offset */
1572
1573 /*ARGSUSED*/
1574 static void
1575 alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1576 contents_size)
1577 bfd *outbfd;
1578 asection *insec;
1579 register arelent ***relocs_ptr;
1580 long *reloc_count_ptr;
1581 char *contents;
1582 bfd_size_type contents_size;
1583 {
1584 long old_reloc_count;
1585 arelent **old_relocs;
1586 register arelent **relocs;
1587
1588 old_reloc_count = *reloc_count_ptr;
1589 old_relocs = *relocs_ptr;
1590 relocs = (arelent **) xmalloc ((old_reloc_count + 3) * sizeof (arelent *));
1591 *relocs_ptr = relocs;
1592
1593 if (nlm_alpha_backend_data (outbfd)->lita_address == 0)
1594 {
1595 bfd *inbfd;
1596 asection *lita_section;
1597
1598 inbfd = insec->owner;
1599 lita_section = bfd_get_section_by_name (inbfd, _LITA);
1600 if (lita_section != (asection *) NULL)
1601 {
1602 nlm_alpha_backend_data (outbfd)->lita_address =
1603 bfd_get_section_vma (inbfd, lita_section);
1604 nlm_alpha_backend_data (outbfd)->lita_size =
1605 bfd_section_size (inbfd, lita_section);
1606 }
1607 else
1608 {
1609 /* Avoid outputting this reloc again. */
1610 nlm_alpha_backend_data (outbfd)->lita_address = 4;
1611 }
1612
1613 *relocs = (arelent *) xmalloc (sizeof (arelent));
1614 (*relocs)->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
1615 (*relocs)->address = nlm_alpha_backend_data (outbfd)->lita_address;
1616 (*relocs)->addend = nlm_alpha_backend_data (outbfd)->lita_size + 1;
1617 (*relocs)->howto = &nlm32_alpha_nw_howto;
1618 ++relocs;
1619 ++(*reloc_count_ptr);
1620 }
1621
1622 /* Get the GP value from bfd. */
1623 if (nlm_alpha_backend_data (outbfd)->gp == 0)
1624 nlm_alpha_backend_data (outbfd)->gp =
1625 bfd_ecoff_get_gp_value (insec->owner);
1626
1627 *relocs = (arelent *) xmalloc (sizeof (arelent));
1628 (*relocs)->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
1629 (*relocs)->address = nlm_alpha_backend_data (outbfd)->gp;
1630 (*relocs)->addend = 0;
1631 (*relocs)->howto = &nlm32_alpha_nw_howto;
1632 ++relocs;
1633 ++(*reloc_count_ptr);
1634
1635 memcpy ((PTR) relocs, (PTR) old_relocs,
1636 (size_t) old_reloc_count * sizeof (arelent *));
1637 relocs[old_reloc_count] = (arelent *) NULL;
1638
1639 free (old_relocs);
1640
1641 if (insec->output_offset != 0)
1642 {
1643 register bfd_size_type i;
1644
1645 for (i = 0; i < old_reloc_count; i++, relocs++)
1646 (*relocs)->address += insec->output_offset;
1647 }
1648 }
1649 /* start-sanitize-powerpc-netware */
1650
1651 /* We keep a linked list of stubs which we must build. Because BFD
1652 requires us to know the sizes of all sections before we can set the
1653 contents of any, we must figure out which stubs we want to build
1654 before we can actually build any of them. */
1655
1656 struct powerpc_stub
1657 {
1658 /* Next stub in linked list. */
1659 struct powerpc_stub *next;
1660
1661 /* Symbol whose value is the start of the stub. This is a symbol
1662 whose name begins with `.'. */
1663 asymbol *start;
1664
1665 /* Symbol we are going to create a reloc against. This is a symbol
1666 with the same name as START but without the leading `.'. */
1667 asymbol *reloc;
1668
1669 /* The TOC index for this stub. This is the index into the TOC
1670 section at which the reloc is created. */
1671 unsigned int toc_index;
1672 };
1673
1674 /* The linked list of stubs. */
1675
1676 static struct powerpc_stub *powerpc_stubs;
1677
1678 /* This is what a stub looks like. The first instruction will get
1679 adjusted with the correct TOC index. */
1680
1681 static unsigned long powerpc_stub_insns[] =
1682 {
1683 0x81820000, /* lwz r12,0(r2) */
1684 0x90410014, /* stw r2,20(r1) */
1685 0x800c0000, /* lwz r0,0(r12) */
1686 0x804c0004, /* lwz r2,r(r12) */
1687 0x7c0903a6, /* mtctr r0 */
1688 0x4e800420, /* bctr */
1689 0, /* Traceback table. */
1690 0xc8000,
1691 0
1692 };
1693
1694 #define POWERPC_STUB_INSN_COUNT \
1695 (sizeof powerpc_stub_insns / sizeof powerpc_stub_insns[0])
1696
1697 #define POWERPC_STUB_SIZE (4 * POWERPC_STUB_INSN_COUNT)
1698
1699 /* Each stub uses a four byte TOC entry. */
1700 #define POWERPC_STUB_TOC_ENTRY_SIZE (4)
1701
1702 /* The original size of the .got section. */
1703 static bfd_size_type powerpc_initial_got_size;
1704
1705 /* Look for all undefined symbols beginning with `.', and prepare to
1706 build a stub for each one. */
1707
1708 static void
1709 powerpc_build_stubs (inbfd, outbfd, symbols_ptr, symcount_ptr)
1710 bfd *inbfd;
1711 bfd *outbfd;
1712 asymbol ***symbols_ptr;
1713 long *symcount_ptr;
1714 {
1715 asection *stub_sec;
1716 asection *got_sec;
1717 unsigned int got_base;
1718 long i;
1719 long symcount;
1720 long stubcount;
1721
1722 /* Make a section to hold stubs. We don't set SEC_HAS_CONTENTS for
1723 the section to prevent copy_sections from reading from it. */
1724 stub_sec = bfd_make_section (inbfd, ".stubs");
1725 if (stub_sec == (asection *) NULL
1726 || ! bfd_set_section_flags (inbfd, stub_sec,
1727 (SEC_CODE
1728 | SEC_RELOC
1729 | SEC_ALLOC
1730 | SEC_LOAD))
1731 || ! bfd_set_section_alignment (inbfd, stub_sec, 2))
1732 bfd_fatal (".stubs");
1733
1734 /* Get the TOC section, which is named .got. */
1735 got_sec = bfd_get_section_by_name (inbfd, ".got");
1736 if (got_sec == (asection *) NULL)
1737 {
1738 got_sec = bfd_make_section (inbfd, ".got");
1739 if (got_sec == (asection *) NULL
1740 || ! bfd_set_section_flags (inbfd, got_sec,
1741 (SEC_DATA
1742 | SEC_RELOC
1743 | SEC_ALLOC
1744 | SEC_LOAD
1745 | SEC_HAS_CONTENTS))
1746 || ! bfd_set_section_alignment (inbfd, got_sec, 2))
1747 bfd_fatal (".got");
1748 }
1749
1750 powerpc_initial_got_size = bfd_section_size (inbfd, got_sec);
1751 got_base = powerpc_initial_got_size;
1752 got_base = (got_base + 3) &~ 3;
1753
1754 stubcount = 0;
1755
1756 symcount = *symcount_ptr;
1757 for (i = 0; i < symcount; i++)
1758 {
1759 asymbol *sym;
1760 asymbol *newsym;
1761 char *newname;
1762 struct powerpc_stub *item;
1763
1764 sym = (*symbols_ptr)[i];
1765
1766 /* We must make a stub for every undefined symbol whose name
1767 starts with '.'. */
1768 if (bfd_asymbol_name (sym)[0] != '.'
1769 || bfd_get_section (sym) != &bfd_und_section)
1770 continue;
1771
1772 /* Make a new undefined symbol with the same name but without
1773 the leading `.'. */
1774 newsym = (asymbol *) xmalloc (sizeof (asymbol));
1775 *newsym = *sym;
1776 newname = (char *) xmalloc (strlen (bfd_asymbol_name (sym)));
1777 strcpy (newname, bfd_asymbol_name (sym) + 1);
1778 newsym->name = newname;
1779
1780 /* Define the `.' symbol to be in the stub section. */
1781 sym->section = stub_sec;
1782 sym->value = stubcount * POWERPC_STUB_SIZE;
1783 /* We set the BSF_DYNAMIC flag here so that we can check it when
1784 we are mangling relocs. FIXME: This is a hack. */
1785 sym->flags = BSF_LOCAL | BSF_DYNAMIC;
1786
1787 /* Add this stub to the linked list. */
1788 item = (struct powerpc_stub *) xmalloc (sizeof (struct powerpc_stub));
1789 item->start = sym;
1790 item->reloc = newsym;
1791 item->toc_index = got_base + stubcount * POWERPC_STUB_TOC_ENTRY_SIZE;
1792
1793 item->next = powerpc_stubs;
1794 powerpc_stubs = item;
1795
1796 ++stubcount;
1797 }
1798
1799 if (stubcount > 0)
1800 {
1801 asymbol **s;
1802 struct powerpc_stub *l;
1803
1804 /* Add the new symbols we just created to the symbol table. */
1805 *symbols_ptr = (asymbol **) xrealloc ((char *) *symbols_ptr,
1806 ((symcount + stubcount)
1807 * sizeof (asymbol)));
1808 *symcount_ptr += stubcount;
1809 s = &(*symbols_ptr)[symcount];
1810 for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1811 *s++ = l->reloc;
1812
1813 /* Set the size of the .stubs section and increase the size of
1814 the .got section. */
1815 if (! bfd_set_section_size (inbfd, stub_sec,
1816 stubcount * POWERPC_STUB_SIZE)
1817 || ! bfd_set_section_size (inbfd, got_sec,
1818 (got_base
1819 + (stubcount
1820 * POWERPC_STUB_TOC_ENTRY_SIZE))))
1821 bfd_fatal ("stub section sizes");
1822 }
1823
1824 /* PowerPC NetWare requires a custom header. We create it here.
1825 The first word is the header version number, currently 1. The
1826 second word is the timestamp of the input file. */
1827 memcpy (nlm_custom_header (outbfd)->stamp, "CuStHeAd", 8);
1828 nlm_custom_header (outbfd)->dataLength = 8;
1829 nlm_custom_header (outbfd)->data = xmalloc (8);
1830 bfd_h_put_32 (outbfd, (bfd_vma) 1,
1831 (bfd_byte *) nlm_custom_header (outbfd)->data);
1832 {
1833 struct stat s;
1834
1835 if (stat (bfd_get_filename (inbfd), &s) < 0)
1836 s.st_mtime = 0;
1837 bfd_h_put_32 (outbfd, (bfd_vma) s.st_mtime,
1838 (bfd_byte *) nlm_custom_header (outbfd)->data + 4);
1839 }
1840 }
1841
1842 /* Resolve all the stubs for PowerPC NetWare. We fill in the contents
1843 of the output section, and create new relocs in the TOC. */
1844
1845 static void
1846 powerpc_resolve_stubs (inbfd, outbfd)
1847 bfd *inbfd;
1848 bfd *outbfd;
1849 {
1850 bfd_byte buf[POWERPC_STUB_SIZE];
1851 unsigned int i;
1852 unsigned int stubcount;
1853 arelent **relocs;
1854 asection *got_sec;
1855 arelent **r;
1856 struct powerpc_stub *l;
1857
1858 if (powerpc_stubs == (struct powerpc_stub *) NULL)
1859 return;
1860
1861 for (i = 0; i < POWERPC_STUB_INSN_COUNT; i++)
1862 bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[i], buf + i * 4);
1863
1864 got_sec = bfd_get_section_by_name (inbfd, ".got");
1865 assert (got_sec != (asection *) NULL);
1866 assert (got_sec->output_section->orelocation == (arelent **) NULL);
1867
1868 stubcount = 0;
1869 for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1870 ++stubcount;
1871 relocs = (arelent **) xmalloc (stubcount * sizeof (arelent *));
1872
1873 r = relocs;
1874 for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1875 {
1876 arelent *reloc;
1877
1878 /* Adjust the first instruction to use the right TOC index. */
1879 bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[0] + l->toc_index, buf);
1880
1881 /* Write this stub out. */
1882 if (! bfd_set_section_contents (outbfd,
1883 bfd_get_section (l->start),
1884 buf,
1885 l->start->value,
1886 POWERPC_STUB_SIZE))
1887 bfd_fatal ("writing stub");
1888
1889 /* Create a new reloc for the TOC entry. */
1890 reloc = (arelent *) xmalloc (sizeof (arelent));
1891 reloc->sym_ptr_ptr = &l->reloc;
1892 reloc->address = l->toc_index + got_sec->output_offset;
1893 reloc->addend = 0;
1894 reloc->howto = bfd_reloc_type_lookup (inbfd, BFD_RELOC_32);
1895
1896 *r++ = reloc;
1897 }
1898
1899 bfd_set_reloc (outbfd, got_sec->output_section, relocs, stubcount);
1900 }
1901
1902 /* Adjust relocation entries for PowerPC NetWare. We do not output
1903 TOC relocations. The object code already contains the offset from
1904 the TOC pointer. When the function is called, the TOC register,
1905 r2, will be set to the correct TOC value, so there is no need for
1906 any further reloc. */
1907
1908 /*ARGSUSED*/
1909 static void
1910 powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1911 contents_size)
1912 bfd *outbfd;
1913 asection *insec;
1914 register arelent ***relocs_ptr;
1915 long *reloc_count_ptr;
1916 char *contents;
1917 bfd_size_type contents_size;
1918 {
1919 const reloc_howto_type *toc_howto;
1920 long reloc_count;
1921 register arelent **relocs;
1922 register long i;
1923
1924 toc_howto = bfd_reloc_type_lookup (insec->owner, BFD_RELOC_PPC_TOC16);
1925 if (toc_howto == (reloc_howto_type *) NULL)
1926 abort ();
1927
1928 /* If this is the .got section, clear out all the contents beyond
1929 the initial size. We must do this here because copy_sections is
1930 going to write out whatever we return in the contents field. */
1931 if (strcmp (bfd_get_section_name (insec->owner, insec), ".got") == 0)
1932 memset (contents + powerpc_initial_got_size, 0,
1933 (bfd_get_section_size_after_reloc (insec)
1934 - powerpc_initial_got_size));
1935
1936 reloc_count = *reloc_count_ptr;
1937 relocs = *relocs_ptr;
1938 for (i = 0; i < reloc_count; i++)
1939 {
1940 arelent *rel;
1941 asymbol *sym;
1942 bfd_vma symvalue;
1943
1944 rel = *relocs++;
1945 sym = *rel->sym_ptr_ptr;
1946
1947 /* We must be able to resolve all PC relative relocs at this
1948 point. If we get a branch to an undefined symbol we build a
1949 stub, since NetWare will resolve undefined symbols into a
1950 pointer to a function descriptor. */
1951 if (rel->howto->pc_relative)
1952 {
1953 /* This check for whether a symbol is in the same section as
1954 the reloc will be wrong if there is a PC relative reloc
1955 between two sections both of which were placed in the
1956 same output section. This should not happen. */
1957 if (bfd_get_section (sym) != insec->output_section)
1958 fprintf (stderr, "%s: unresolved PC relative reloc against %s\n",
1959 program_name, bfd_asymbol_name (sym));
1960 else
1961 {
1962 bfd_vma val;
1963
1964 assert (rel->howto->size == 2 && rel->howto->pcrel_offset);
1965 val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address);
1966 val = ((val &~ rel->howto->dst_mask)
1967 | (((val & rel->howto->src_mask)
1968 + (sym->value - rel->address)
1969 + rel->addend)
1970 & rel->howto->dst_mask));
1971 bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
1972
1973 /* If this reloc is against an stubbed symbol and the
1974 next instruction is
1975 cror 31,31,31
1976 then we replace the next instruction with
1977 lwz r2,20(r1)
1978 This reloads the TOC pointer after a stub call. */
1979 if (bfd_asymbol_name (sym)[0] == '.'
1980 && (sym->flags & BSF_DYNAMIC) != 0
1981 && (bfd_get_32 (outbfd,
1982 (bfd_byte *) contents + rel->address + 4)
1983 == 0x4ffffb82)) /* cror 31,31,31 */
1984 bfd_put_32 (outbfd, (bfd_vma) 0x80410014, /* lwz r2,20(r1) */
1985 (bfd_byte *) contents + rel->address + 4);
1986
1987 --*reloc_count_ptr;
1988 --relocs;
1989 memmove (relocs, relocs + 1,
1990 (size_t) ((reloc_count - 1) * sizeof (arelent *)));
1991 continue;
1992 }
1993 }
1994
1995 /* When considering a TOC reloc, we do not want to include the
1996 symbol value. The symbol will be start of the TOC section
1997 (which is named .got). We do want to include the addend. */
1998 if (rel->howto == toc_howto)
1999 symvalue = 0;
2000 else
2001 symvalue = sym->value;
2002
2003 /* If this is a relocation against a symbol with a value, or
2004 there is a reloc addend, we need to update the addend in the
2005 object file. */
2006 if (symvalue + rel->addend != 0)
2007 {
2008 bfd_vma val;
2009
2010 switch (rel->howto->size)
2011 {
2012 case 1:
2013 val = bfd_get_16 (outbfd,
2014 (bfd_byte *) contents + rel->address);
2015 val = ((val &~ rel->howto->dst_mask)
2016 | (((val & rel->howto->src_mask)
2017 + symvalue
2018 + rel->addend)
2019 & rel->howto->dst_mask));
2020 if ((bfd_signed_vma) val < - 0x8000
2021 || (bfd_signed_vma) val >= 0x8000)
2022 fprintf (stderr,
2023 "%s: overflow when adjusting relocation against %s\n",
2024 program_name, bfd_asymbol_name (sym));
2025 bfd_put_16 (outbfd, val, (bfd_byte *) contents + rel->address);
2026 break;
2027
2028 case 2:
2029 val = bfd_get_32 (outbfd,
2030 (bfd_byte *) contents + rel->address);
2031 val = ((val &~ rel->howto->dst_mask)
2032 | (((val & rel->howto->src_mask)
2033 + symvalue
2034 + rel->addend)
2035 & rel->howto->dst_mask));
2036 bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
2037 break;
2038
2039 default:
2040 abort ();
2041 }
2042
2043 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
2044 rel->addend = 0;
2045 }
2046
2047 /* Now that we have incorporated the addend, remove any TOC
2048 relocs. */
2049 if (rel->howto == toc_howto)
2050 {
2051 --*reloc_count_ptr;
2052 --relocs;
2053 memmove (relocs, relocs + 1,
2054 (size_t) ((reloc_count - i) * sizeof (arelent *)));
2055 continue;
2056 }
2057
2058 rel->address += insec->output_offset;
2059 }
2060 }
2061 /* end-sanitize-powerpc-netware */
2062 \f
2063 /* Name of linker. */
2064 #ifndef LD_NAME
2065 #define LD_NAME "ld"
2066 #endif
2067
2068 /* Temporary file name base. */
2069 static char *temp_filename;
2070
2071 /* The user has specified several input files. Invoke the linker to
2072 link them all together, and convert and delete the resulting output
2073 file. */
2074
2075 static char *
2076 link_inputs (inputs, ld)
2077 struct string_list *inputs;
2078 char *ld;
2079 {
2080 size_t c;
2081 struct string_list *q;
2082 char **argv;
2083 size_t i;
2084 int pid;
2085 int status;
2086
2087 c = 0;
2088 for (q = inputs; q != NULL; q = q->next)
2089 ++c;
2090
2091 argv = (char **) alloca (c + 5);
2092
2093 #ifndef __MSDOS__
2094 if (ld == NULL)
2095 {
2096 char *p;
2097
2098 /* Find the linker to invoke based on how nlmconv was run. */
2099 p = program_name + strlen (program_name);
2100 while (p != program_name)
2101 {
2102 if (p[-1] == '/')
2103 {
2104 ld = (char *) xmalloc (p - program_name + strlen (LD_NAME) + 1);
2105 memcpy (ld, program_name, p - program_name);
2106 strcpy (ld + (p - program_name), LD_NAME);
2107 break;
2108 }
2109 --p;
2110 }
2111 }
2112 #endif
2113
2114 if (ld == NULL)
2115 ld = (char *) LD_NAME;
2116
2117 choose_temp_base ();
2118
2119 unlink_on_exit = xmalloc (strlen (temp_filename) + 3);
2120 sprintf (unlink_on_exit, "%s.O", temp_filename);
2121
2122 argv[0] = ld;
2123 argv[1] = (char *) "-r";
2124 argv[2] = (char *) "-o";
2125 argv[3] = unlink_on_exit;
2126 i = 4;
2127 for (q = inputs; q != NULL; q = q->next, i++)
2128 argv[i] = q->string;
2129 argv[i] = NULL;
2130
2131 if (debug)
2132 {
2133 for (i = 0; argv[i] != NULL; i++)
2134 fprintf (stderr, " %s", argv[i]);
2135 fprintf (stderr, "\n");
2136 }
2137
2138 pid = pexecute (ld, argv);
2139
2140 if (waitpid (pid, &status, 0) < 0)
2141 {
2142 perror ("waitpid");
2143 unlink (unlink_on_exit);
2144 exit (1);
2145 }
2146
2147 if (status != 0)
2148 {
2149 fprintf (stderr, "%s: Execution of %s failed\n", program_name, ld);
2150 unlink (unlink_on_exit);
2151 exit (1);
2152 }
2153
2154 return unlink_on_exit;
2155 }
2156
2157 /* Choose a temporary file name. Stolen from gcc.c. */
2158
2159 static const char *
2160 choose_temp_base_try (try, base)
2161 const char *try;
2162 const char *base;
2163 {
2164 const char *rv;
2165
2166 if (base)
2167 rv = base;
2168 else if (try == NULL)
2169 rv = NULL;
2170 else if (access (try, R_OK | W_OK) != 0)
2171 rv = NULL;
2172 else
2173 rv = try;
2174 return rv;
2175 }
2176
2177 static void
2178 choose_temp_base ()
2179 {
2180 const char *base = NULL;
2181 int len;
2182
2183 base = choose_temp_base_try (getenv ("TMPDIR"), base);
2184 base = choose_temp_base_try (getenv ("TMP"), base);
2185 base = choose_temp_base_try (getenv ("TEMP"), base);
2186
2187 #ifdef P_tmpdir
2188 base = choose_temp_base_try (P_tmpdir, base);
2189 #endif
2190
2191 base = choose_temp_base_try ("/usr/tmp", base);
2192 base = choose_temp_base_try ("/tmp", base);
2193
2194 /* If all else fails, use the current directory! */
2195 if (base == NULL)
2196 base = "./";
2197
2198 len = strlen (base);
2199 temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1);
2200 strcpy (temp_filename, base);
2201 if (len > 0 && temp_filename[len-1] != '/')
2202 temp_filename[len++] = '/';
2203 strcpy (temp_filename + len, "ccXXXXXX");
2204
2205 mktemp (temp_filename);
2206 if (*temp_filename == '\0')
2207 abort ();
2208 }
2209
2210 /* Execute a job. Stolen from gcc.c. */
2211
2212 #ifndef OS2
2213 #ifdef __MSDOS__
2214
2215 static int
2216 pexecute (program, argv)
2217 char *program;
2218 char *argv[];
2219 {
2220 char *scmd, *rf;
2221 FILE *argfile;
2222 int i;
2223
2224 scmd = (char *)malloc (strlen (program) + strlen (temp_filename) + 10);
2225 rf = scmd + strlen(program) + 2 + el;
2226 sprintf (scmd, "%s.exe @%s.gp", program, temp_filename);
2227 argfile = fopen (rf, "w");
2228 if (argfile == 0)
2229 pfatal_with_name (rf);
2230
2231 for (i=1; argv[i]; i++)
2232 {
2233 char *cp;
2234 for (cp = argv[i]; *cp; cp++)
2235 {
2236 if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
2237 fputc ('\\', argfile);
2238 fputc (*cp, argfile);
2239 }
2240 fputc ('\n', argfile);
2241 }
2242 fclose (argfile);
2243
2244 i = system (scmd);
2245
2246 remove (rf);
2247
2248 if (i == -1)
2249 {
2250 perror (program);
2251 return MIN_FATAL_STATUS << 8;
2252 }
2253
2254 return i << 8;
2255 }
2256
2257 #else /* not __MSDOS__ */
2258
2259 static int
2260 pexecute (program, argv)
2261 char *program;
2262 char *argv[];
2263 {
2264 int pid;
2265 int retries, sleep_interval;
2266
2267 /* Fork a subprocess; wait and retry if it fails. */
2268 sleep_interval = 1;
2269 for (retries = 0; retries < 4; retries++)
2270 {
2271 pid = vfork ();
2272 if (pid >= 0)
2273 break;
2274 sleep (sleep_interval);
2275 sleep_interval *= 2;
2276 }
2277
2278 switch (pid)
2279 {
2280 case -1:
2281 #ifdef vfork
2282 perror ("fork");
2283 #else
2284 perror ("vfork");
2285 #endif
2286 exit (1);
2287 /* NOTREACHED */
2288 return 0;
2289
2290 case 0: /* child */
2291 /* Exec the program. */
2292 execvp (program, argv);
2293 perror (program);
2294 exit (1);
2295 /* NOTREACHED */
2296 return 0;
2297
2298 default:
2299 /* Return child's process number. */
2300 return pid;
2301 }
2302 }
2303
2304 #endif /* not __MSDOS__ */
2305 #else /* not OS2 */
2306
2307 static int
2308 pexecute (program, argv)
2309 char *program;
2310 char *argv[];
2311 {
2312 return spawnvp (1, program, argv);
2313 }
2314 #endif /* not OS2 */
This page took 0.076456 seconds and 4 git commands to generate.