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