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