Restore changes clobbered by Sean's check in.
[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 <assert.h>
36 #include <getopt.h>
37 #include <bfd.h>
38 #include "sysdep.h"
39 #include "bucomm.h"
40 /* Internal BFD NLM header.  */
41 #include "libnlm.h"
42 #include "nlmconv.h"
43
44 /* If strerror is just a macro, we want to use the one from libiberty
45    since it will handle undefined values.  */
46 #undef strerror
47 extern char *strerror ();
48
49 #ifndef localtime
50 extern struct tm *localtime ();
51 #endif
52
53 #ifndef SEEK_SET
54 #define SEEK_SET 0
55 #endif
56 \f
57 /* Global variables.  */
58
59 /* The name used to invoke the program.  */
60 char *program_name;
61
62 /* The version number.  */
63 extern char *program_version;
64
65 /* Local variables.  */
66
67 /* The symbol table.  */
68 static asymbol **symbols;
69
70 /* The list of long options.  */
71 static struct option long_options[] =
72 {
73   { "header-info", required_argument, 0, 'T' },
74   { "help", no_argument, 0, 'h' },
75   { "input-format", required_argument, 0, 'I' },
76   { "output-format", required_argument, 0, 'O' },
77   { "version", no_argument, 0, 'V' },
78   { NULL, no_argument, 0, 0 }
79 };
80
81 /* Local routines.  */
82
83 static void show_help PARAMS ((void));
84 static void show_usage PARAMS ((FILE *, int));
85 static const char *select_output_format PARAMS ((enum bfd_architecture,
86                                                  long, boolean));
87 static void setup_sections PARAMS ((bfd *, asection *, PTR));
88 static void copy_sections PARAMS ((bfd *, asection *, PTR));
89 static void mangle_relocs PARAMS ((bfd *, asection *, arelent **,
90                                    bfd_size_type *, char *,
91                                    bfd_size_type));
92 static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent **,
93                                         bfd_size_type *, char *,
94                                         bfd_size_type));
95 static void sparc_mangle_relocs PARAMS ((bfd *, asection *, arelent **,
96                                         bfd_size_type *, char *,
97                                         bfd_size_type));
98 \f
99 /* The main routine.  */
100
101 int
102 main (argc, argv)
103      int argc;
104      char **argv;
105 {
106   int opt;
107   const char *input_format = NULL;
108   const char *output_format = NULL;
109   const char *header_file = NULL;
110   bfd *inbfd;
111   bfd *outbfd;
112   asymbol **newsyms, **outsyms;
113   unsigned int symcount, newsymalloc, newsymcount;
114   asection *bss_sec, *data_sec;
115   bfd_vma vma;
116   bfd_size_type align;
117   asymbol *endsym;
118   unsigned int i;
119   char inlead, outlead;
120   boolean gotstart, gotexit, gotcheck;
121   struct stat st;
122   FILE *custom_data, *help_data, *message_data, *rpc_data, *shared_data;
123   bfd_size_type custom_size, help_size, message_size, module_size, rpc_size;
124   asection *custom_section, *help_section, *message_section, *module_section;
125   asection *rpc_section, *shared_section;
126   bfd *sharedbfd;
127   bfd_size_type shared_offset, shared_size;
128   Nlm_Internal_Fixed_Header sharedhdr;
129   int len;
130   char *modname;
131
132   program_name = argv[0];
133
134   bfd_init ();
135
136   while ((opt = getopt_long (argc, argv, "hI:O:T:V", long_options, (int *) 0))
137          != EOF)
138     {
139       switch (opt)
140         {
141         case 'h':
142           show_help ();
143           /*NOTREACHED*/
144         case 'I':
145           input_format = optarg;
146           break;
147         case 'O':
148           output_format = optarg;
149           break;
150         case 'T':
151           header_file = optarg;
152           break;
153         case 'V':
154           printf ("GNU %s version %s\n", program_name, program_version);
155           exit (0);
156           /*NOTREACHED*/
157         case 0:
158           break;
159         default:
160           show_usage (stderr, 1);
161           /*NOTREACHED*/
162         }
163     }
164
165   if (optind + 2 != argc)
166     show_usage (stderr, 1);
167
168   if (strcmp (argv[optind], argv[optind + 1]) == 0)
169     {
170       fprintf (stderr, "%s: input and output files must be different\n",
171                program_name);
172       exit (1);
173     }
174
175   inbfd = bfd_openr (argv[optind], input_format);
176   if (inbfd == NULL)
177     bfd_fatal (argv[optind]);
178
179   if (! bfd_check_format (inbfd, bfd_object))
180     bfd_fatal (argv[optind]);
181
182   if (output_format == NULL)
183     output_format = select_output_format (bfd_get_arch (inbfd),
184                                           bfd_get_mach (inbfd),
185                                           inbfd->xvec->byteorder_big_p);
186
187   assert (output_format != NULL);
188   outbfd = bfd_openw (argv[optind + 1], output_format);
189   if (outbfd == NULL)
190     bfd_fatal (argv[optind + 1]);
191   if (! bfd_set_format (outbfd, bfd_object))
192     bfd_fatal (argv[optind + 1]);
193
194   assert (outbfd->xvec->flavour == bfd_target_nlm_flavour);
195
196   if (bfd_arch_get_compatible (inbfd, outbfd) == NULL)
197     fprintf (stderr,
198              "%s: warning:input and output formats are not compatible\n",
199              program_name);
200
201   /* Initialize the header information to default values.  */
202   fixed_hdr = nlm_fixed_header (outbfd);
203   var_hdr = nlm_variable_header (outbfd);
204   version_hdr = nlm_version_header (outbfd);
205   copyright_hdr = nlm_copyright_header (outbfd);
206   extended_hdr = nlm_extended_header (outbfd);
207   check_procedure = NULL;
208   custom_file = NULL;
209   debug_info = false;
210   exit_procedure = "_Stop";
211   export_symbols = NULL;
212   map_file = NULL;
213   full_map = false;
214   help_file = NULL;
215   import_symbols = NULL;
216   message_file = NULL;
217   modules = NULL;
218   sharelib_file = NULL;
219   start_procedure = "_Prelude";
220   verbose = false;
221   rpc_file = NULL;
222
223   parse_errors = 0;
224
225   /* Parse the header file (if there is one).  */
226   if (header_file != NULL)
227     {
228       if (! nlmlex_file (header_file)
229           || yyparse () != 0
230           || parse_errors != 0)
231         exit (1);
232     }
233
234   /* Start copying the input BFD to the output BFD.  */
235   if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd)))
236     bfd_fatal (bfd_get_filename (outbfd));
237
238   symbols = (asymbol **) xmalloc (get_symtab_upper_bound (inbfd));
239   symcount = bfd_canonicalize_symtab (inbfd, symbols);
240
241   /* Make sure we have a .bss section.  */
242   bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME);
243   if (bss_sec == NULL)
244     {
245       bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME);
246       if (bss_sec == NULL
247           || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC)
248           || ! bfd_set_section_alignment (outbfd, bss_sec, 1))
249         bfd_fatal ("make .bss section");
250     }
251
252   /* Set up the sections.  */
253   bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);
254
255   /* The .bss section immediately follows the .data section.  */
256   data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME);
257   if (data_sec != NULL)
258     {
259       bfd_size_type add;
260
261       vma = bfd_get_section_size_before_reloc (data_sec);
262       align = 1 << bss_sec->alignment_power;
263       add = ((vma + align - 1) &~ (align - 1)) - vma;
264       vma += add;
265       if (! bfd_set_section_vma (outbfd, bss_sec, vma))
266         bfd_fatal ("set .bss vma");
267       if (add != 0)
268         {
269           bfd_size_type data_size;
270
271           data_size = bfd_get_section_size_before_reloc (data_sec);
272           if (! bfd_set_section_size (outbfd, data_sec, data_size + add))
273             bfd_fatal ("set .data size");
274         }
275     }
276
277   /* Adjust symbol information.  */
278   inlead = bfd_get_symbol_leading_char (inbfd);
279   outlead = bfd_get_symbol_leading_char (outbfd);
280   gotstart = false;
281   gotexit = false;
282   gotcheck = false;
283   newsymalloc = 10;
284   newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *));
285   newsymcount = 0;
286   endsym = NULL;
287   for (i = 0; i < symcount; i++)
288     {
289       register asymbol *sym;
290
291       sym = symbols[i];
292
293       /* Add or remove a leading underscore.  */
294       if (inlead != outlead)
295         {
296           if (inlead != '\0')
297             {
298               if (bfd_asymbol_name (sym)[0] == inlead)
299                 {
300                   if (outlead == '\0')
301                     ++sym->name;
302                   else
303                     {
304                       char *new;
305
306                       new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1);
307                       new[0] = outlead;
308                       strcpy (new + 1, bfd_asymbol_name (sym) + 1);
309                       sym->name = new;
310                     }
311                 }
312             }
313           else
314             {
315               char *new;
316
317               new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2);
318               new[0] = outlead;
319               strcpy (new + 1, bfd_asymbol_name (sym));
320               sym->name = new;
321             }
322         }
323
324       /* NLM's have an uninitialized data section, but they do not
325          have a common section in the Unix sense.  Move all common
326          symbols into the .bss section, and mark them as exported.  */
327       if (bfd_is_com_section (bfd_get_section (sym)))
328         {
329           bfd_vma size;
330
331           sym->section = bss_sec;
332           size = sym->value;
333           sym->value = bss_sec->_raw_size;
334           bss_sec->_raw_size += size;
335           align = 1 << bss_sec->alignment_power;
336           bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1);
337           sym->flags |= BSF_EXPORT | BSF_GLOBAL;
338         }
339       else if (bfd_get_section (sym)->output_section != NULL)
340         {
341           /* Move the symbol into the output section.  */
342           sym->value += bfd_get_section (sym)->output_offset;
343           sym->section = bfd_get_section (sym)->output_section;
344           /* This is no longer a section symbol.  */
345           sym->flags &=~ BSF_SECTION_SYM;
346         }
347
348       /* Force _edata and _end to be defined.  This would normally be
349          done by the linker, but the manipulation of the common
350          symbols will confuse it.  */
351       if (bfd_asymbol_name (sym)[0] == '_'
352           && bfd_get_section (sym) == &bfd_und_section)
353         {
354           if (strcmp (bfd_asymbol_name (sym), "_edata") == 0)
355             {
356               sym->section = bss_sec;
357               sym->value = 0;
358             }
359           if (strcmp (bfd_asymbol_name (sym), "_end") == 0)
360             {
361               sym->section = bss_sec;
362               endsym = sym;
363             }
364         }
365
366       /* If this is a global symbol, check the export list.  */
367       if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0)
368         {
369           register struct string_list *l;
370           int found_simple;
371
372           /* Unfortunately, a symbol can appear multiple times on the
373              export list, with and without prefixes.  */
374           found_simple = 0;
375           for (l = export_symbols; l != NULL; l = l->next)
376             {
377               if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
378                 found_simple = 1;
379               else
380                 {
381                   char *zbase;
382
383                   zbase = strchr (l->string, '@');
384                   if (zbase != NULL
385                       && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
386                     {
387                       /* We must add a symbol with this prefix.  */
388                       if (newsymcount >= newsymalloc)
389                         {
390                           newsymalloc += 10;
391                           newsyms = ((asymbol **)
392                                      xrealloc (newsyms,
393                                                (newsymalloc
394                                                 * sizeof (asymbol *))));
395                         }
396                       newsyms[newsymcount] =
397                         (asymbol *) xmalloc (sizeof (asymbol));
398                       *newsyms[newsymcount] = *sym;
399                       newsyms[newsymcount]->name = l->string;
400                       ++newsymcount;
401                     }
402                 }
403             }
404           if (! found_simple)
405             {
406               /* The unmodified symbol is actually not exported at
407                  all.  */
408               sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT);
409               sym->flags |= BSF_LOCAL;
410             }
411         }
412
413       /* If it's an undefined symbol, see if it's on the import list.
414          Change the prefix if necessary.  */
415       if (bfd_get_section (sym) == &bfd_und_section
416           && import_symbols != NULL)
417         {
418           register struct string_list *l;
419
420           for (l = import_symbols; l != NULL; l = l->next)
421             {
422               if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
423                 break;
424               else
425                 {
426                   char *zbase;
427
428                   zbase = strchr (l->string, '@');
429                   if (zbase != NULL
430                       && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
431                     {
432                       sym->name = l->string;
433                       break;
434                     }
435                 }
436             }
437           if (l == NULL)
438             fprintf (stderr,
439                      "%s: warning: symbol %s imported but not in import list\n",
440                      program_name, bfd_asymbol_name (sym));
441         }
442         
443       /* See if it's one of the special named symbols.  */
444       if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0)
445         {
446           if (! bfd_set_start_address (outbfd, bfd_asymbol_value (sym)))
447             bfd_fatal ("set start address");
448           gotstart = true;
449         }
450       if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0)
451         {
452           nlm_fixed_header (outbfd)->exitProcedureOffset =
453             bfd_asymbol_value (sym);
454           gotexit = true;
455         }
456       if (check_procedure != NULL
457           && strcmp (bfd_asymbol_name (sym), check_procedure) == 0)
458         {
459           nlm_fixed_header (outbfd)->checkUnloadProcedureOffset =
460             bfd_asymbol_value (sym);
461           gotcheck = true;
462         }
463     }
464
465   if (endsym != NULL)
466     endsym->value = bfd_get_section_size_before_reloc (bss_sec);
467
468   if (newsymcount == 0)
469     outsyms = symbols;
470   else
471     {
472       outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1)
473                                       * sizeof (asymbol *));
474       memcpy (outsyms, symbols, symcount * sizeof (asymbol *));
475       memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *));
476       outsyms[symcount + newsymcount] = NULL;
477     }
478
479   bfd_set_symtab (outbfd, outsyms, symcount + newsymcount);
480     
481   if (! gotstart)
482     fprintf (stderr, "%s: warning: START procedure %s not defined\n",
483              program_name, start_procedure);
484   if (! gotexit)
485     fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n",
486              program_name, exit_procedure);
487   if (check_procedure != NULL
488       && ! gotcheck)
489     fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n",
490              program_name, check_procedure);
491
492   /* Add additional sections required for the header information.  */
493   if (custom_file != NULL)
494     {
495       custom_data = fopen (custom_file, "r");
496       if (custom_data == NULL
497           || fstat (fileno (custom_data), &st) < 0)
498         {
499           fprintf (stderr, "%s:%s: %s\n", program_name, custom_file,
500                    strerror (errno));
501           custom_file = NULL;
502         }
503       else
504         {
505           custom_size = st.st_size;
506           custom_section = bfd_make_section (outbfd, ".nlmcustom");
507           if (custom_section == NULL
508               || ! bfd_set_section_size (outbfd, custom_section, custom_size)
509               || ! bfd_set_section_flags (outbfd, custom_section,
510                                           SEC_HAS_CONTENTS))
511             bfd_fatal ("custom section");
512         }
513     }
514   if (help_file != NULL)
515     {
516       help_data = fopen (help_file, "r");
517       if (help_data == NULL
518           || fstat (fileno (help_data), &st) < 0)
519         {
520           fprintf (stderr, "%s:%s: %s\n", program_name, help_file,
521                    strerror (errno));
522           help_file = NULL;
523         }
524       else
525         {
526           help_size = st.st_size;
527           help_section = bfd_make_section (outbfd, ".nlmhelp");
528           if (help_section == NULL
529               || ! bfd_set_section_size (outbfd, help_section, help_size)
530               || ! bfd_set_section_flags (outbfd, help_section,
531                                           SEC_HAS_CONTENTS))
532             bfd_fatal ("help section");
533           strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
534         }
535     }
536   if (message_file != NULL)
537     {
538       message_data = fopen (message_file, "r");
539       if (message_data == NULL
540           || fstat (fileno (message_data), &st) < 0)
541         {
542           fprintf (stderr, "%s:%s: %s\n", program_name, message_file,
543                    strerror (errno));
544           message_file = NULL;
545         }
546       else
547         {
548           message_size = st.st_size;
549           message_section = bfd_make_section (outbfd, ".nlmmessages");
550           if (message_section == NULL
551               || ! bfd_set_section_size (outbfd, message_section, message_size)
552               || ! bfd_set_section_flags (outbfd, message_section,
553                                           SEC_HAS_CONTENTS))
554             bfd_fatal ("message section");
555           strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
556         }
557     }
558   if (modules != NULL)
559     {
560       struct string_list *l;
561
562       module_size = 0;
563       for (l = modules; l != NULL; l = l->next)
564         module_size += strlen (l->string) + 1;
565       module_section = bfd_make_section (outbfd, ".nlmmodules");
566       if (module_section == NULL
567           || ! bfd_set_section_size (outbfd, module_section, module_size)
568           || ! bfd_set_section_flags (outbfd, module_section,
569                                       SEC_HAS_CONTENTS))
570         bfd_fatal ("module section");
571     }
572   if (rpc_file != NULL)
573     {
574       rpc_data = fopen (rpc_file, "r");
575       if (rpc_data == NULL
576           || fstat (fileno (rpc_data), &st) < 0)
577         {
578           fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file,
579                    strerror (errno));
580           rpc_file = NULL;
581         }
582       else
583         {
584           rpc_size = st.st_size;
585           rpc_section = bfd_make_section (outbfd, ".nlmrpc");
586           if (rpc_section == NULL
587               || ! bfd_set_section_size (outbfd, rpc_section, rpc_size)
588               || ! bfd_set_section_flags (outbfd, rpc_section,
589                                           SEC_HAS_CONTENTS))
590             bfd_fatal ("rpc section");
591           strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
592         }
593     }
594   if (sharelib_file != NULL)
595     {
596       sharedbfd = bfd_openr (sharelib_file, output_format);
597       if (sharedbfd == NULL
598           || ! bfd_check_format (sharedbfd, bfd_object))
599         {
600           fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
601                    bfd_errmsg (bfd_error));
602           sharelib_file = NULL;
603         }
604       else
605         {
606           sharedhdr = *nlm_fixed_header (sharedbfd);
607           bfd_close (sharedbfd);
608           shared_data = fopen (sharelib_file, "r");
609           if (shared_data == NULL
610               || (fstat (fileno (shared_data), &st) < 0))
611             {
612               fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
613                        strerror (errno));
614               sharelib_file = NULL;
615             }
616           else
617             {
618               /* If we were clever, we could just copy out the
619                  sections of the shared library which we actually
620                  need.  However, we would have to figure out the sizes
621                  of the external and public information, and that can
622                  not be done without reading through them.  */
623               shared_offset = st.st_size;
624               if (shared_offset > sharedhdr.codeImageOffset)
625                 shared_offset = sharedhdr.codeImageOffset;
626               if (shared_offset > sharedhdr.dataImageOffset)
627                 shared_offset = sharedhdr.dataImageOffset;
628               if (shared_offset > sharedhdr.relocationFixupOffset)
629                 shared_offset = sharedhdr.relocationFixupOffset;
630               if (shared_offset > sharedhdr.externalReferencesOffset)
631                 shared_offset = sharedhdr.externalReferencesOffset;
632               if (shared_offset > sharedhdr.publicsOffset)
633                 shared_offset = sharedhdr.publicsOffset;
634               shared_size = st.st_size - shared_offset;
635               shared_section = bfd_make_section (outbfd, ".nlmshared");
636               if (shared_section == NULL
637                   || ! bfd_set_section_size (outbfd, shared_section,
638                                              shared_size)
639                   || ! bfd_set_section_flags (outbfd, shared_section,
640                                               SEC_HAS_CONTENTS))
641                 bfd_fatal ("shared section");
642               strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
643             }
644         }
645     }
646
647   /* Check whether a version was given.  */
648   if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0)
649     fprintf (stderr, "%s: warning: No version number given\n",
650              program_name);
651
652   /* At least for now, always create an extended header, because that
653      is what NLMLINK does.  */
654   strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
655
656   /* If the date was not given, force it in.  */
657   if (nlm_version_header (outbfd)->month == 0
658       && nlm_version_header (outbfd)->day == 0
659       && nlm_version_header (outbfd)->year == 0)
660     {
661       time_t now;
662       struct tm *ptm;
663
664       time (&now);
665       ptm = localtime (&now);
666       nlm_version_header (outbfd)->month = ptm->tm_mon + 1;
667       nlm_version_header (outbfd)->day = ptm->tm_mday;
668       nlm_version_header (outbfd)->year = ptm->tm_year + 1900;
669       strncpy (version_hdr->stamp, "VeRsIoN#", 8);
670     }
671
672   /* Copy over the sections.  */
673   bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd);
674
675   /* Finish up the header information.  */
676   if (custom_file != NULL)
677     {
678       PTR data;
679
680       data = xmalloc (custom_size);
681       if (fread (data, 1, custom_size, custom_data) != custom_size)
682         fprintf (stderr, "%s:%s: read: %s\n", program_name, custom_file,
683                  strerror (errno));
684       else
685         {
686           if (! bfd_set_section_contents (outbfd, custom_section, data,
687                                           (file_ptr) 0, custom_size))
688             bfd_fatal ("custom section");
689           nlm_fixed_header (outbfd)->customDataOffset =
690             custom_section->filepos;
691           nlm_fixed_header (outbfd)->customDataSize = custom_size;
692         }
693       free (data);
694     }
695   if (! debug_info)
696     {
697       /* As a special hack, the backend recognizes a debugInfoOffset
698          of -1 to mean that it should not output any debugging
699          information.  This can not be handling by fiddling with the
700          symbol table because exported symbols appear in both the
701          export information and the debugging information.  */
702       nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1;
703     }
704   if (map_file != NULL)
705     fprintf (stderr,
706              "%s: MAP and FULLMAP are not supported; try ld -M\n",
707              program_name);
708   if (help_file != NULL)
709     {
710       PTR data;
711
712       data = xmalloc (help_size);
713       if (fread (data, 1, help_size, help_data) != help_size)
714         fprintf (stderr, "%s:%s: read: %s\n", program_name, help_file,
715                  strerror (errno));
716       else
717         {
718           if (! bfd_set_section_contents (outbfd, help_section, data,
719                                           (file_ptr) 0, help_size))
720             bfd_fatal ("help section");
721           nlm_extended_header (outbfd)->helpFileOffset =
722             help_section->filepos;
723           nlm_extended_header (outbfd)->helpFileLength = help_size;
724         }
725       free (data);
726     }
727   if (message_file != NULL)
728     {
729       PTR data;
730
731       data = xmalloc (message_size);
732       if (fread (data, 1, message_size, message_data) != message_size)
733         fprintf (stderr, "%s:%s: read: %s\n", program_name, message_file,
734                  strerror (errno));
735       else
736         {
737           if (! bfd_set_section_contents (outbfd, message_section, data,
738                                           (file_ptr) 0, message_size))
739             bfd_fatal ("message section");
740           nlm_extended_header (outbfd)->messageFileOffset =
741             message_section->filepos;
742           nlm_extended_header (outbfd)->messageFileLength = message_size;
743
744           /* FIXME: Are these offsets correct on all platforms?  Are
745              they 32 bits on all platforms?  What endianness?  */
746           nlm_extended_header (outbfd)->languageID =
747             bfd_h_get_32 (outbfd, (bfd_byte *) data + 106);
748           nlm_extended_header (outbfd)->messageCount =
749             bfd_h_get_32 (outbfd, (bfd_byte *) data + 110);
750         }
751       free (data);
752     }
753   if (modules != NULL)
754     {
755       PTR data;
756       char *set;
757       struct string_list *l;
758       bfd_size_type c;
759
760       data = xmalloc (module_size);
761       c = 0;
762       set = (char *) data;
763       for (l = modules; l != NULL; l = l->next)
764         {
765           *set = strlen (l->string);
766           strncpy (set + 1, l->string, *set);
767           set += *set + 1;
768           ++c;
769         }
770       if (! bfd_set_section_contents (outbfd, module_section, data,
771                                       (file_ptr) 0, module_size))
772         bfd_fatal ("module section");
773       nlm_fixed_header (outbfd)->moduleDependencyOffset =
774         module_section->filepos;
775       nlm_fixed_header (outbfd)->numberOfModuleDependencies = c;
776     }
777   if (rpc_file != NULL)
778     {
779       PTR data;
780
781       data = xmalloc (rpc_size);
782       if (fread (data, 1, rpc_size, rpc_data) != rpc_size)
783         fprintf (stderr, "%s:%s: read: %s\n", program_name, rpc_file,
784                  strerror (errno));
785       else
786         {
787           if (! bfd_set_section_contents (outbfd, rpc_section, data,
788                                           (file_ptr) 0, rpc_size))
789             bfd_fatal ("rpc section");
790           nlm_extended_header (outbfd)->RPCDataOffset =
791             rpc_section->filepos;
792           nlm_extended_header (outbfd)->RPCDataLength = rpc_size;
793         }
794       free (data);
795     }
796   if (sharelib_file != NULL)
797     {
798       PTR data;
799
800       data = xmalloc (shared_size);
801       if (fseek (shared_data, shared_offset, SEEK_SET) != 0
802           || fread (data, 1, shared_size, shared_data) != shared_size)
803         fprintf (stderr, "%s:%s: read: %s\n", program_name, sharelib_file,
804                  strerror (errno));
805       else
806         {
807           if (! bfd_set_section_contents (outbfd, shared_section, data,
808                                           (file_ptr) 0, shared_size))
809             bfd_fatal ("shared section");
810         }
811       nlm_extended_header (outbfd)->sharedCodeOffset =
812         sharedhdr.codeImageOffset - shared_offset + shared_section->filepos;
813       nlm_extended_header (outbfd)->sharedCodeLength =
814         sharedhdr.codeImageSize;
815       nlm_extended_header (outbfd)->sharedDataOffset =
816         sharedhdr.dataImageOffset - shared_offset + shared_section->filepos;
817       nlm_extended_header (outbfd)->sharedDataLength =
818         sharedhdr.dataImageSize;
819       nlm_extended_header (outbfd)->sharedRelocationFixupOffset =
820         (sharedhdr.relocationFixupOffset
821          - shared_offset
822          + shared_section->filepos);
823       nlm_extended_header (outbfd)->sharedRelocationFixupCount =
824         sharedhdr.numberOfRelocationFixups;
825       nlm_extended_header (outbfd)->sharedExternalReferenceOffset =
826         (sharedhdr.externalReferencesOffset
827          - shared_offset
828          + shared_section->filepos);
829       nlm_extended_header (outbfd)->sharedExternalReferenceCount =
830         sharedhdr.numberOfExternalReferences;
831       nlm_extended_header (outbfd)->sharedPublicsOffset =
832         sharedhdr.publicsOffset - shared_offset + shared_section->filepos;
833       nlm_extended_header (outbfd)->sharedPublicsCount =
834         sharedhdr.numberOfPublics;
835       nlm_extended_header (outbfd)->sharedDebugRecordOffset =
836         sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos;
837       nlm_extended_header (outbfd)->sharedDebugRecordCount =
838         sharedhdr.numberOfDebugRecords;
839       nlm_extended_header (outbfd)->SharedInitializationOffset =
840         sharedhdr.codeStartOffset;
841       nlm_extended_header (outbfd)->SharedExitProcedureOffset =
842         sharedhdr.exitProcedureOffset;
843       free (data);
844     }
845   len = strlen (argv[optind + 1]);
846   if (len > NLM_MODULE_NAME_SIZE - 2)
847     len = NLM_MODULE_NAME_SIZE - 2;
848   nlm_fixed_header (outbfd)->moduleName[0] = len;
849
850   strncpy (nlm_fixed_header (outbfd)->moduleName + 1, argv[optind + 1],
851            NLM_MODULE_NAME_SIZE - 2);
852   nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0';
853   for (modname = nlm_fixed_header (outbfd)->moduleName;
854        *modname != '\0';
855        modname++)
856     if (islower (*modname))
857       *modname = toupper (*modname);
858
859   strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
860            NLM_OLD_THREAD_NAME_LENGTH);
861
862   if (! bfd_close (outbfd))
863     bfd_fatal (argv[optind + 1]);
864   if (! bfd_close (inbfd))
865     bfd_fatal (argv[optind]);
866
867   return 0;
868 }
869 \f
870 /* Display a help message and exit.  */
871
872 static void
873 show_help ()
874 {
875   printf ("%s: Convert an object file into a NetWare Loadable Module\n",
876           program_name);
877   show_usage (stdout, 0);
878 }
879
880 /* Show a usage message and exit.  */
881
882 static void
883 show_usage (file, status)
884      FILE *file;
885      int status;
886 {
887   fprintf (file, "\
888 Usage: %s [-hV] [-I format] [-O format] [-T header-file]\n\
889        [--input-format=format] [--output-format=format]\n\
890        [--header-file=file] [--help] [--version]\n\
891        in-file out-file\n",
892            program_name);
893   exit (status);
894 }
895 \f
896 /* Select the output format based on the input architecture, machine,
897    and endianness.  This chooses the appropriate NLM target.  */
898
899 static const char *
900 select_output_format (arch, mach, bigendian)
901      enum bfd_architecture arch;
902      long mach;
903      boolean bigendian;
904 {
905   switch (arch)
906     {
907     case bfd_arch_i386:
908       return "nlm32-i386";
909     case bfd_arch_sparc:
910       return "nlm32-sparc";
911     default:
912       fprintf (stderr, "%s: no default NLM format for %s\n",
913                program_name, bfd_printable_arch_mach (arch, mach));
914       exit (1);
915       /* Avoid warning.  */
916       return NULL;
917     }
918   /*NOTREACHED*/
919 }
920 \f
921 /* The BFD sections are copied in two passes.  This function selects
922    the output section for each input section, and sets up the section
923    name, size, etc.  */
924
925 static void
926 setup_sections (inbfd, insec, data_ptr)
927      bfd *inbfd;
928      asection *insec;
929      PTR data_ptr;
930 {
931   bfd *outbfd = (bfd *) data_ptr;
932   flagword f;
933   const char *outname;
934   asection *outsec;
935
936   f = bfd_get_section_flags (inbfd, insec);
937   if (f & SEC_CODE)
938     outname = NLM_CODE_NAME;
939   else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS))
940     outname = NLM_INITIALIZED_DATA_NAME;
941   else if (f & SEC_ALLOC)
942     outname = NLM_UNINITIALIZED_DATA_NAME;
943   else
944     outname = bfd_section_name (inbfd, insec);
945
946   outsec = bfd_get_section_by_name (outbfd, outname);
947   if (outsec == NULL)
948     {
949       outsec = bfd_make_section (outbfd, outname);
950       if (outsec == NULL)
951         bfd_fatal ("make section");
952     }
953
954   insec->output_section = outsec;
955   insec->output_offset = bfd_section_size (outbfd, outsec);
956
957   if (! bfd_set_section_size (outbfd, outsec,
958                               (bfd_section_size (outbfd, outsec)
959                                + bfd_section_size (inbfd, insec))))
960     bfd_fatal ("set section size");
961
962   if ((bfd_section_alignment (inbfd, insec)
963        > bfd_section_alignment (outbfd, outsec))
964       && ! bfd_set_section_alignment (outbfd, outsec,
965                                       bfd_section_alignment (inbfd, insec)))
966     bfd_fatal ("set section alignment");
967
968   if (! bfd_set_section_flags (outbfd, outsec, f))
969     bfd_fatal ("set section flags");
970 }
971
972 /* Copy the section contents.  */
973
974 static void
975 copy_sections (inbfd, insec, data_ptr)
976      bfd *inbfd;
977      asection *insec;
978      PTR data_ptr;
979 {
980   bfd *outbfd = (bfd *) data_ptr;
981   asection *outsec;
982   bfd_size_type size;
983   PTR contents;
984   bfd_size_type reloc_size;
985
986   outsec = insec->output_section;
987   assert (outsec != NULL);
988
989   size = bfd_get_section_size_before_reloc (insec);
990   if (size == 0)
991     return;
992
993   /* FIXME: Why are these necessary?  */
994   insec->_cooked_size = insec->_raw_size;
995   insec->reloc_done = true;
996
997   if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
998     contents = NULL;
999   else
1000     {
1001       contents = xmalloc (size);
1002       if (! bfd_get_section_contents (inbfd, insec, contents,
1003                                       (file_ptr) 0, size))
1004         bfd_fatal (bfd_get_filename (inbfd));
1005     }
1006
1007   reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
1008   if (reloc_size == 0)
1009     bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
1010   else
1011     {
1012       arelent **relocs;
1013       bfd_size_type reloc_count;
1014
1015       relocs = (arelent **) xmalloc (reloc_size);
1016       reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols);
1017       mangle_relocs (outbfd, insec, relocs, &reloc_count, (char *) contents,
1018                      size);
1019       bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
1020     }
1021
1022   if (contents != NULL)
1023     {
1024       if (! bfd_set_section_contents (outbfd, outsec, contents,
1025                                       insec->output_offset, size))
1026         bfd_fatal (bfd_get_filename (outbfd));
1027       free (contents);
1028     }
1029 }
1030
1031 /* Some, perhaps all, NetWare targets require changing the relocs used
1032    by the input formats.  */
1033
1034 static void
1035 mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents, contents_size)
1036      bfd *outbfd;
1037      asection *insec;
1038      arelent **relocs;
1039      bfd_size_type *reloc_count_ptr;
1040      char *contents;
1041      bfd_size_type contents_size;
1042 {
1043   switch (bfd_get_arch (outbfd))
1044     {
1045     case bfd_arch_i386:
1046       i386_mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents,
1047                           contents_size);
1048       break;
1049     default:
1050       break;
1051     }
1052 }
1053
1054 /* NetWare on the i386 supports a restricted set of relocs, which are
1055    different from those used on other i386 targets.  This routine
1056    converts the relocs.  It is, obviously, very target dependent.  At
1057    the moment, the nlm32-i386 backend performs similar translations;
1058    however, it is more reliable and efficient to do them here.  */
1059
1060 static reloc_howto_type nlm_i386_pcrel_howto =
1061   HOWTO (1,                     /* type */
1062          0,                     /* rightshift */
1063          2,                     /* size (0 = byte, 1 = short, 2 = long) */
1064          32,                    /* bitsize */
1065          true,                  /* pc_relative */
1066          0,                     /* bitpos */
1067          complain_overflow_signed, /* complain_on_overflow */
1068          0,                     /* special_function */
1069          "DISP32",              /* name */
1070          true,                  /* partial_inplace */
1071          0xffffffff,            /* src_mask */
1072          0xffffffff,            /* dst_mask */
1073          true);                 /* pcrel_offset */
1074
1075 static void
1076 i386_mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents,
1077                     contents_size)
1078      bfd *outbfd;
1079      asection *insec;
1080      arelent **relocs;
1081      bfd_size_type *reloc_count_ptr;
1082      char *contents;
1083      bfd_size_type contents_size;
1084 {
1085   bfd_size_type reloc_count, i;
1086
1087   reloc_count = *reloc_count_ptr;
1088   for (i = 0; i < reloc_count; i++)
1089     {
1090       arelent *rel;
1091       asymbol *sym;
1092       bfd_size_type address;
1093       bfd_vma addend;
1094
1095       rel = *relocs++;
1096       sym = *rel->sym_ptr_ptr;
1097
1098       /* We're moving the relocs from the input section to the output
1099          section, so we must adjust the address accordingly.  */
1100       address = rel->address;
1101       rel->address += insec->output_offset;
1102
1103       /* Note that no serious harm will ensue if we fail to change a
1104          reloc.  The backend will fail when writing out the reloc.  */
1105
1106       /* Make sure this reloc is within the data we have.  We use only
1107          4 byte relocs here, so we insist on having 4 bytes.  */
1108       if (address + 4 > contents_size)
1109         continue;
1110
1111       /* A PC relative reloc entirely within a single section is
1112          completely unnecessary.  This can be generated by ld -r.  */
1113       if (sym == insec->symbol
1114           && rel->howto != NULL
1115           && rel->howto->pc_relative
1116           && ! rel->howto->pcrel_offset)
1117         {
1118           --*reloc_count_ptr;
1119           --relocs;
1120           memmove (relocs, relocs + 1,
1121                    (reloc_count - i) * sizeof (arelent *));
1122           continue;
1123         }
1124
1125       /* Get the amount the relocation will add in.  */
1126       addend = rel->addend + sym->value;
1127
1128       /* NetWare doesn't support PC relative relocs against defined
1129          symbols, so we have to eliminate them by doing the relocation
1130          now.  We can only do this if the reloc is within a single
1131          section.  */
1132       if (rel->howto != NULL
1133           && rel->howto->pc_relative
1134           && bfd_get_section (sym) == insec->output_section)
1135         {
1136           bfd_vma val;
1137
1138           if (rel->howto->pcrel_offset)
1139             addend -= address;
1140
1141           val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1142           val += addend;
1143           bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1144
1145           --*reloc_count_ptr;
1146           --relocs;
1147           memmove (relocs, relocs + 1,
1148                    (reloc_count - i) * sizeof (arelent *));
1149           continue;
1150         }
1151
1152       /* NetWare doesn't support reloc addends, so we get rid of them
1153          here by simply adding them into the object data.  We handle
1154          the symbol value, if any, the same way.  */
1155       if (addend != 0
1156           && rel->howto != NULL
1157           && rel->howto->rightshift == 0
1158           && rel->howto->size == 2
1159           && rel->howto->bitsize == 32
1160           && rel->howto->bitpos == 0
1161           && rel->howto->src_mask == 0xffffffff
1162           && rel->howto->dst_mask == 0xffffffff)
1163         {
1164           bfd_vma val;
1165
1166           val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1167           val += addend;
1168           bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1169
1170           /* Adjust the reloc for the changes we just made.  */
1171           rel->addend = 0;
1172           if (bfd_get_section (sym) != &bfd_und_section)
1173             rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
1174         }
1175
1176       /* NetWare uses a reloc with pcrel_offset set.  We adjust
1177          pc_relative relocs accordingly.  We are going to change the
1178          howto field, so we can only do this if the current one is
1179          compatible.  We should check that special_function is NULL
1180          here, but at the moment coff-i386 uses a special_function
1181          which does not affect what we are doing here.  */
1182       if (rel->howto != NULL
1183           && rel->howto->pc_relative
1184           && ! rel->howto->pcrel_offset
1185           && rel->howto->rightshift == 0
1186           && rel->howto->size == 2
1187           && rel->howto->bitsize == 32
1188           && rel->howto->bitpos == 0
1189           && rel->howto->src_mask == 0xffffffff
1190           && rel->howto->dst_mask == 0xffffffff)
1191         {
1192           bfd_vma val;
1193
1194           /* When pcrel_offset is not set, it means that the negative
1195              of the address of the memory location is stored in the
1196              memory location.  We must add it back in.  */
1197           val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1198           val += address;
1199           bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1200
1201           /* We must change to a new howto.  */
1202           rel->howto = &nlm_i386_pcrel_howto;
1203         }
1204     }
1205 }