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