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