1 /* nlmconv.c -- NLM conversion program
2 Copyright (C) 1993 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
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.
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.
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. */
20 /* Written by Ian Lance Taylor <ian@cygnus.com>.
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. */
33 #include <sys/types.h>
40 /* Internal BFD NLM header. */
44 /* If strerror is just a macro, we want to use the one from libiberty
45 since it will handle undefined values. */
47 extern char *strerror ();
50 extern struct tm *localtime ();
57 /* Global variables. */
59 /* The name used to invoke the program. */
62 /* The version number. */
63 extern char *program_version;
65 /* Local variables. */
67 /* The symbol table. */
68 static asymbol **symbols;
70 /* The list of long options. */
71 static struct option long_options[] =
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 }
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,
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 *,
92 static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent **,
93 bfd_size_type *, char *,
95 static void sparc_mangle_relocs PARAMS ((bfd *, asection *, arelent **,
96 bfd_size_type *, char *,
99 /* The main routine. */
107 const char *input_format = NULL;
108 const char *output_format = NULL;
109 const char *header_file = NULL;
112 asymbol **newsyms, **outsyms;
113 unsigned int symcount, newsymalloc, newsymcount;
114 asection *bss_sec, *data_sec;
119 char inlead, outlead;
120 boolean gotstart, gotexit, gotcheck;
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;
127 bfd_size_type shared_offset, shared_size;
128 Nlm_Internal_Fixed_Header sharedhdr;
132 program_name = argv[0];
136 while ((opt = getopt_long (argc, argv, "hI:O:T:V", long_options, (int *) 0))
145 input_format = optarg;
148 output_format = optarg;
151 header_file = optarg;
154 printf ("GNU %s version %s\n", program_name, program_version);
160 show_usage (stderr, 1);
165 if (optind + 2 != argc)
166 show_usage (stderr, 1);
168 if (strcmp (argv[optind], argv[optind + 1]) == 0)
170 fprintf (stderr, "%s: input and output files must be different\n",
175 inbfd = bfd_openr (argv[optind], input_format);
177 bfd_fatal (argv[optind]);
179 if (! bfd_check_format (inbfd, bfd_object))
180 bfd_fatal (argv[optind]);
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);
187 assert (output_format != NULL);
188 outbfd = bfd_openw (argv[optind + 1], output_format);
190 bfd_fatal (argv[optind + 1]);
191 if (! bfd_set_format (outbfd, bfd_object))
192 bfd_fatal (argv[optind + 1]);
194 assert (outbfd->xvec->flavour == bfd_target_nlm_flavour);
196 if (bfd_arch_get_compatible (inbfd, outbfd) == NULL)
198 "%s: warning:input and output formats are not compatible\n",
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;
210 exit_procedure = "_Stop";
211 export_symbols = NULL;
215 import_symbols = NULL;
218 sharelib_file = NULL;
219 start_procedure = "_Prelude";
225 /* Parse the header file (if there is one). */
226 if (header_file != NULL)
228 if (! nlmlex_file (header_file)
230 || parse_errors != 0)
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));
238 symbols = (asymbol **) xmalloc (get_symtab_upper_bound (inbfd));
239 symcount = bfd_canonicalize_symtab (inbfd, symbols);
241 /* Make sure we have a .bss section. */
242 bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME);
245 bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME);
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");
252 /* Set up the sections. */
253 bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);
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)
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;
265 if (! bfd_set_section_vma (outbfd, bss_sec, vma))
266 bfd_fatal ("set .bss vma");
269 bfd_size_type data_size;
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");
277 /* Adjust symbol information. */
278 inlead = bfd_get_symbol_leading_char (inbfd);
279 outlead = bfd_get_symbol_leading_char (outbfd);
284 newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *));
287 for (i = 0; i < symcount; i++)
289 register asymbol *sym;
293 /* Add or remove a leading underscore. */
294 if (inlead != outlead)
298 if (bfd_asymbol_name (sym)[0] == inlead)
306 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1);
308 strcpy (new + 1, bfd_asymbol_name (sym) + 1);
317 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2);
319 strcpy (new + 1, bfd_asymbol_name (sym));
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)))
331 sym->section = bss_sec;
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;
339 else if (bfd_get_section (sym)->output_section != NULL)
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;
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)
354 if (strcmp (bfd_asymbol_name (sym), "_edata") == 0)
356 sym->section = bss_sec;
359 if (strcmp (bfd_asymbol_name (sym), "_end") == 0)
361 sym->section = bss_sec;
366 /* If this is a global symbol, check the export list. */
367 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0)
369 register struct string_list *l;
372 /* Unfortunately, a symbol can appear multiple times on the
373 export list, with and without prefixes. */
375 for (l = export_symbols; l != NULL; l = l->next)
377 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
383 zbase = strchr (l->string, '@');
385 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
387 /* We must add a symbol with this prefix. */
388 if (newsymcount >= newsymalloc)
391 newsyms = ((asymbol **)
394 * sizeof (asymbol *))));
396 newsyms[newsymcount] =
397 (asymbol *) xmalloc (sizeof (asymbol));
398 *newsyms[newsymcount] = *sym;
399 newsyms[newsymcount]->name = l->string;
406 /* The unmodified symbol is actually not exported at
408 sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT);
409 sym->flags |= BSF_LOCAL;
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)
418 register struct string_list *l;
420 for (l = import_symbols; l != NULL; l = l->next)
422 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
428 zbase = strchr (l->string, '@');
430 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
432 sym->name = l->string;
439 "%s: warning: symbol %s imported but not in import list\n",
440 program_name, bfd_asymbol_name (sym));
443 /* See if it's one of the special named symbols. */
444 if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0)
446 if (! bfd_set_start_address (outbfd, bfd_asymbol_value (sym)))
447 bfd_fatal ("set start address");
450 if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0)
452 nlm_fixed_header (outbfd)->exitProcedureOffset =
453 bfd_asymbol_value (sym);
456 if (check_procedure != NULL
457 && strcmp (bfd_asymbol_name (sym), check_procedure) == 0)
459 nlm_fixed_header (outbfd)->checkUnloadProcedureOffset =
460 bfd_asymbol_value (sym);
466 endsym->value = bfd_get_section_size_before_reloc (bss_sec);
468 if (newsymcount == 0)
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;
479 bfd_set_symtab (outbfd, outsyms, symcount + newsymcount);
482 fprintf (stderr, "%s: warning: START procedure %s not defined\n",
483 program_name, start_procedure);
485 fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n",
486 program_name, exit_procedure);
487 if (check_procedure != NULL
489 fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n",
490 program_name, check_procedure);
492 /* Add additional sections required for the header information. */
493 if (custom_file != NULL)
495 custom_data = fopen (custom_file, "r");
496 if (custom_data == NULL
497 || fstat (fileno (custom_data), &st) < 0)
499 fprintf (stderr, "%s:%s: %s\n", program_name, custom_file,
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,
511 bfd_fatal ("custom section");
514 if (help_file != NULL)
516 help_data = fopen (help_file, "r");
517 if (help_data == NULL
518 || fstat (fileno (help_data), &st) < 0)
520 fprintf (stderr, "%s:%s: %s\n", program_name, help_file,
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,
532 bfd_fatal ("help section");
533 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
536 if (message_file != NULL)
538 message_data = fopen (message_file, "r");
539 if (message_data == NULL
540 || fstat (fileno (message_data), &st) < 0)
542 fprintf (stderr, "%s:%s: %s\n", program_name, message_file,
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,
554 bfd_fatal ("message section");
555 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
560 struct string_list *l;
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,
570 bfd_fatal ("module section");
572 if (rpc_file != NULL)
574 rpc_data = fopen (rpc_file, "r");
576 || fstat (fileno (rpc_data), &st) < 0)
578 fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file,
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,
590 bfd_fatal ("rpc section");
591 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
594 if (sharelib_file != NULL)
596 sharedbfd = bfd_openr (sharelib_file, output_format);
597 if (sharedbfd == NULL
598 || ! bfd_check_format (sharedbfd, bfd_object))
600 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
601 bfd_errmsg (bfd_error));
602 sharelib_file = NULL;
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))
612 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
614 sharelib_file = NULL;
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,
639 || ! bfd_set_section_flags (outbfd, shared_section,
641 bfd_fatal ("shared section");
642 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
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",
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);
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)
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);
672 /* Copy over the sections. */
673 bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd);
675 /* Finish up the header information. */
676 if (custom_file != NULL)
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,
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;
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;
704 if (map_file != NULL)
706 "%s: MAP and FULLMAP are not supported; try ld -M\n",
708 if (help_file != NULL)
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,
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;
727 if (message_file != NULL)
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,
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;
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);
757 struct string_list *l;
760 data = xmalloc (module_size);
763 for (l = modules; l != NULL; l = l->next)
765 *set = strlen (l->string);
766 strncpy (set + 1, l->string, *set);
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;
777 if (rpc_file != NULL)
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,
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;
796 if (sharelib_file != NULL)
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,
807 if (! bfd_set_section_contents (outbfd, shared_section, data,
808 (file_ptr) 0, shared_size))
809 bfd_fatal ("shared section");
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
822 + shared_section->filepos);
823 nlm_extended_header (outbfd)->sharedRelocationFixupCount =
824 sharedhdr.numberOfRelocationFixups;
825 nlm_extended_header (outbfd)->sharedExternalReferenceOffset =
826 (sharedhdr.externalReferencesOffset
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;
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;
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;
856 if (islower (*modname))
857 *modname = toupper (*modname);
859 strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
860 NLM_OLD_THREAD_NAME_LENGTH);
862 if (! bfd_close (outbfd))
863 bfd_fatal (argv[optind + 1]);
864 if (! bfd_close (inbfd))
865 bfd_fatal (argv[optind]);
870 /* Display a help message and exit. */
875 printf ("%s: Convert an object file into a NetWare Loadable Module\n",
877 show_usage (stdout, 0);
880 /* Show a usage message and exit. */
883 show_usage (file, status)
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\
896 /* Select the output format based on the input architecture, machine,
897 and endianness. This chooses the appropriate NLM target. */
900 select_output_format (arch, mach, bigendian)
901 enum bfd_architecture arch;
910 return "nlm32-sparc";
912 fprintf (stderr, "%s: no default NLM format for %s\n",
913 program_name, bfd_printable_arch_mach (arch, mach));
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
926 setup_sections (inbfd, insec, data_ptr)
931 bfd *outbfd = (bfd *) data_ptr;
936 f = bfd_get_section_flags (inbfd, insec);
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;
944 outname = bfd_section_name (inbfd, insec);
946 outsec = bfd_get_section_by_name (outbfd, outname);
949 outsec = bfd_make_section (outbfd, outname);
951 bfd_fatal ("make section");
954 insec->output_section = outsec;
955 insec->output_offset = bfd_section_size (outbfd, outsec);
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");
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");
968 if (! bfd_set_section_flags (outbfd, outsec, f))
969 bfd_fatal ("set section flags");
972 /* Copy the section contents. */
975 copy_sections (inbfd, insec, data_ptr)
980 bfd *outbfd = (bfd *) data_ptr;
984 bfd_size_type reloc_size;
986 outsec = insec->output_section;
987 assert (outsec != NULL);
989 size = bfd_get_section_size_before_reloc (insec);
993 /* FIXME: Why are these necessary? */
994 insec->_cooked_size = insec->_raw_size;
995 insec->reloc_done = true;
997 if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
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));
1007 reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
1008 if (reloc_size == 0)
1009 bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
1013 bfd_size_type reloc_count;
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,
1019 bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
1022 if (contents != NULL)
1024 if (! bfd_set_section_contents (outbfd, outsec, contents,
1025 insec->output_offset, size))
1026 bfd_fatal (bfd_get_filename (outbfd));
1031 /* Some, perhaps all, NetWare targets require changing the relocs used
1032 by the input formats. */
1035 mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents, contents_size)
1039 bfd_size_type *reloc_count_ptr;
1041 bfd_size_type contents_size;
1043 switch (bfd_get_arch (outbfd))
1046 i386_mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents,
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. */
1060 static reloc_howto_type nlm_i386_pcrel_howto =
1061 HOWTO (1, /* type */
1063 2, /* size (0 = byte, 1 = short, 2 = long) */
1065 true, /* pc_relative */
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 */
1076 i386_mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents,
1081 bfd_size_type *reloc_count_ptr;
1083 bfd_size_type contents_size;
1085 bfd_size_type reloc_count, i;
1087 reloc_count = *reloc_count_ptr;
1088 for (i = 0; i < reloc_count; i++)
1092 bfd_size_type address;
1096 sym = *rel->sym_ptr_ptr;
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;
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. */
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)
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)
1120 memmove (relocs, relocs + 1,
1121 (reloc_count - i) * sizeof (arelent *));
1125 /* Get the amount the relocation will add in. */
1126 addend = rel->addend + sym->value;
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
1132 if (rel->howto != NULL
1133 && rel->howto->pc_relative
1134 && bfd_get_section (sym) == insec->output_section)
1138 if (rel->howto->pcrel_offset)
1141 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1143 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1147 memmove (relocs, relocs + 1,
1148 (reloc_count - i) * sizeof (arelent *));
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. */
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)
1166 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1168 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1170 /* Adjust the reloc for the changes we just made. */
1172 if (bfd_get_section (sym) != &bfd_und_section)
1173 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
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)
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);
1199 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1201 /* We must change to a new howto. */
1202 rel->howto = &nlm_i386_pcrel_howto;