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