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