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 *,
96 /* The main routine. */
104 const char *input_format = NULL;
105 const char *output_format = NULL;
106 const char *header_file = NULL;
109 asymbol **newsyms, **outsyms;
110 unsigned int symcount, newsymalloc, newsymcount;
111 asection *bss_sec, *data_sec;
116 char inlead, outlead;
117 boolean gotstart, gotexit, gotcheck;
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;
124 bfd_size_type shared_offset, shared_size;
125 Nlm_Internal_Fixed_Header sharedhdr;
129 program_name = argv[0];
133 while ((opt = getopt_long (argc, argv, "hI:O:T:V", long_options, (int *) 0))
142 input_format = optarg;
145 output_format = optarg;
148 header_file = optarg;
151 printf ("GNU %s version %s\n", program_name, program_version);
157 show_usage (stderr, 1);
162 if (optind + 2 != argc)
163 show_usage (stderr, 1);
165 if (strcmp (argv[optind], argv[optind + 1]) == 0)
167 fprintf (stderr, "%s: input and output files must be different\n",
172 inbfd = bfd_openr (argv[optind], input_format);
174 bfd_fatal (argv[optind]);
176 if (! bfd_check_format (inbfd, bfd_object))
177 bfd_fatal (argv[optind]);
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);
184 assert (output_format != NULL);
185 outbfd = bfd_openw (argv[optind + 1], output_format);
187 bfd_fatal (argv[optind + 1]);
188 if (! bfd_set_format (outbfd, bfd_object))
189 bfd_fatal (argv[optind + 1]);
191 assert (outbfd->xvec->flavour == bfd_target_nlm_flavour);
193 if (bfd_arch_get_compatible (inbfd, outbfd) == NULL)
195 "%s: warning:input and output formats are not compatible\n",
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;
207 exit_procedure = "_Stop";
208 export_symbols = NULL;
212 import_symbols = NULL;
215 sharelib_file = NULL;
216 start_procedure = "_Prelude";
222 /* Parse the header file (if there is one). */
223 if (header_file != NULL)
225 if (! nlmlex_file (header_file)
227 || parse_errors != 0)
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));
235 symbols = (asymbol **) xmalloc (get_symtab_upper_bound (inbfd));
236 symcount = bfd_canonicalize_symtab (inbfd, symbols);
238 /* Make sure we have a .bss section. */
239 bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME);
242 bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME);
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");
249 /* Set up the sections. */
250 bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);
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)
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;
262 if (! bfd_set_section_vma (outbfd, bss_sec, vma))
263 bfd_fatal ("set .bss vma");
266 bfd_size_type data_size;
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");
274 /* Adjust symbol information. */
275 inlead = bfd_get_symbol_leading_char (inbfd);
276 outlead = bfd_get_symbol_leading_char (outbfd);
281 newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *));
284 for (i = 0; i < symcount; i++)
286 register asymbol *sym;
290 /* Add or remove a leading underscore. */
291 if (inlead != outlead)
295 if (bfd_asymbol_name (sym)[0] == inlead)
303 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1);
305 strcpy (new + 1, bfd_asymbol_name (sym) + 1);
314 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2);
316 strcpy (new + 1, bfd_asymbol_name (sym));
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)))
328 sym->section = bss_sec;
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;
336 else if (bfd_get_section (sym)->output_section != NULL)
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;
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)
351 if (strcmp (bfd_asymbol_name (sym), "_edata") == 0)
353 sym->section = bss_sec;
356 if (strcmp (bfd_asymbol_name (sym), "_end") == 0)
358 sym->section = bss_sec;
363 /* If this is a global symbol, check the export list. */
364 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0)
366 register struct string_list *l;
369 /* Unfortunately, a symbol can appear multiple times on the
370 export list, with and without prefixes. */
372 for (l = export_symbols; l != NULL; l = l->next)
374 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
380 zbase = strchr (l->string, '@');
382 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
384 /* We must add a symbol with this prefix. */
385 if (newsymcount >= newsymalloc)
388 newsyms = ((asymbol **)
391 * sizeof (asymbol *))));
393 newsyms[newsymcount] =
394 (asymbol *) xmalloc (sizeof (asymbol));
395 *newsyms[newsymcount] = *sym;
396 newsyms[newsymcount]->name = l->string;
403 /* The unmodified symbol is actually not exported at
405 sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT);
406 sym->flags |= BSF_LOCAL;
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)
415 register struct string_list *l;
417 for (l = import_symbols; l != NULL; l = l->next)
419 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
425 zbase = strchr (l->string, '@');
427 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
429 sym->name = l->string;
436 "%s: warning: symbol %s imported but not in import list\n",
437 program_name, bfd_asymbol_name (sym));
440 /* See if it's one of the special named symbols. */
441 if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0)
443 if (! bfd_set_start_address (outbfd, bfd_asymbol_value (sym)))
444 bfd_fatal ("set start address");
447 if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0)
449 nlm_fixed_header (outbfd)->exitProcedureOffset =
450 bfd_asymbol_value (sym);
453 if (check_procedure != NULL
454 && strcmp (bfd_asymbol_name (sym), check_procedure) == 0)
456 nlm_fixed_header (outbfd)->checkUnloadProcedureOffset =
457 bfd_asymbol_value (sym);
463 endsym->value = bfd_get_section_size_before_reloc (bss_sec);
465 if (newsymcount == 0)
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;
476 bfd_set_symtab (outbfd, outsyms, symcount + newsymcount);
479 fprintf (stderr, "%s: warning: START procedure %s not defined\n",
480 program_name, start_procedure);
482 fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n",
483 program_name, exit_procedure);
484 if (check_procedure != NULL
486 fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n",
487 program_name, check_procedure);
489 /* Add additional sections required for the header information. */
490 if (custom_file != NULL)
492 custom_data = fopen (custom_file, "r");
493 if (custom_data == NULL
494 || fstat (fileno (custom_data), &st) < 0)
496 fprintf (stderr, "%s:%s: %s\n", program_name, custom_file,
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,
508 bfd_fatal ("custom section");
511 if (help_file != NULL)
513 help_data = fopen (help_file, "r");
514 if (help_data == NULL
515 || fstat (fileno (help_data), &st) < 0)
517 fprintf (stderr, "%s:%s: %s\n", program_name, help_file,
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,
529 bfd_fatal ("help section");
530 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
533 if (message_file != NULL)
535 message_data = fopen (message_file, "r");
536 if (message_data == NULL
537 || fstat (fileno (message_data), &st) < 0)
539 fprintf (stderr, "%s:%s: %s\n", program_name, message_file,
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,
551 bfd_fatal ("message section");
552 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
557 struct string_list *l;
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,
567 bfd_fatal ("module section");
569 if (rpc_file != NULL)
571 rpc_data = fopen (rpc_file, "r");
573 || fstat (fileno (rpc_data), &st) < 0)
575 fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file,
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,
587 bfd_fatal ("rpc section");
588 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
591 if (sharelib_file != NULL)
593 sharedbfd = bfd_openr (sharelib_file, output_format);
594 if (sharedbfd == NULL
595 || ! bfd_check_format (sharedbfd, bfd_object))
597 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
598 bfd_errmsg (bfd_error));
599 sharelib_file = NULL;
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))
609 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
611 sharelib_file = NULL;
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,
636 || ! bfd_set_section_flags (outbfd, shared_section,
638 bfd_fatal ("shared section");
639 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
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",
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);
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)
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);
669 /* Copy over the sections. */
670 bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd);
672 /* Finish up the header information. */
673 if (custom_file != NULL)
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,
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;
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;
701 if (map_file != NULL)
703 "%s: MAP and FULLMAP are not supported; try ld -M\n",
705 if (help_file != NULL)
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,
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;
724 if (message_file != NULL)
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,
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;
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);
754 struct string_list *l;
757 data = xmalloc (module_size);
760 for (l = modules; l != NULL; l = l->next)
762 *set = strlen (l->string);
763 strncpy (set + 1, l->string, *set);
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;
774 if (rpc_file != NULL)
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,
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;
793 if (sharelib_file != NULL)
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,
804 if (! bfd_set_section_contents (outbfd, shared_section, data,
805 (file_ptr) 0, shared_size))
806 bfd_fatal ("shared section");
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
819 + shared_section->filepos);
820 nlm_extended_header (outbfd)->sharedRelocationFixupCount =
821 sharedhdr.numberOfRelocationFixups;
822 nlm_extended_header (outbfd)->sharedExternalReferenceOffset =
823 (sharedhdr.externalReferencesOffset
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)->sharedDebugRecordOffset =
833 sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos;
834 nlm_extended_header (outbfd)->sharedDebugRecordCount =
835 sharedhdr.numberOfDebugRecords;
836 nlm_extended_header (outbfd)->SharedInitializationOffset =
837 sharedhdr.codeStartOffset;
838 nlm_extended_header (outbfd)->SharedExitProcedureOffset =
839 sharedhdr.exitProcedureOffset;
842 len = strlen (argv[optind + 1]);
843 if (len > NLM_MODULE_NAME_SIZE - 2)
844 len = NLM_MODULE_NAME_SIZE - 2;
845 nlm_fixed_header (outbfd)->moduleName[0] = len;
847 strncpy (nlm_fixed_header (outbfd)->moduleName + 1, argv[optind + 1],
848 NLM_MODULE_NAME_SIZE - 2);
849 nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0';
850 for (modname = nlm_fixed_header (outbfd)->moduleName;
853 if (islower (*modname))
854 *modname = toupper (*modname);
856 strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
857 NLM_OLD_THREAD_NAME_LENGTH);
859 if (! bfd_close (outbfd))
860 bfd_fatal (argv[optind + 1]);
861 if (! bfd_close (inbfd))
862 bfd_fatal (argv[optind]);
867 /* Display a help message and exit. */
872 printf ("%s: Convert an object file into a NetWare Loadable Module\n",
874 show_usage (stdout, 0);
877 /* Show a usage message and exit. */
880 show_usage (file, status)
885 Usage: %s [-hV] [-I format] [-O format] [-T header-file]\n\
886 [--input-format=format] [--output-format=format]\n\
887 [--header-file=file] [--help] [--version]\n\
893 /* Select the output format based on the input architecture, machine,
894 and endianness. This chooses the appropriate NLM target. */
897 select_output_format (arch, mach, bigendian)
898 enum bfd_architecture arch;
907 return "nlm32-sparc";
909 fprintf (stderr, "%s: no default NLM format for %s\n",
910 program_name, bfd_printable_arch_mach (arch, mach));
918 /* The BFD sections are copied in two passes. This function selects
919 the output section for each input section, and sets up the section
923 setup_sections (inbfd, insec, data_ptr)
928 bfd *outbfd = (bfd *) data_ptr;
933 f = bfd_get_section_flags (inbfd, insec);
935 outname = NLM_CODE_NAME;
936 else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS))
937 outname = NLM_INITIALIZED_DATA_NAME;
938 else if (f & SEC_ALLOC)
939 outname = NLM_UNINITIALIZED_DATA_NAME;
941 outname = bfd_section_name (inbfd, insec);
943 outsec = bfd_get_section_by_name (outbfd, outname);
946 outsec = bfd_make_section (outbfd, outname);
948 bfd_fatal ("make section");
951 insec->output_section = outsec;
952 insec->output_offset = bfd_section_size (outbfd, outsec);
954 if (! bfd_set_section_size (outbfd, outsec,
955 (bfd_section_size (outbfd, outsec)
956 + bfd_section_size (inbfd, insec))))
957 bfd_fatal ("set section size");
959 if ((bfd_section_alignment (inbfd, insec)
960 > bfd_section_alignment (outbfd, outsec))
961 && ! bfd_set_section_alignment (outbfd, outsec,
962 bfd_section_alignment (inbfd, insec)))
963 bfd_fatal ("set section alignment");
965 if (! bfd_set_section_flags (outbfd, outsec, f))
966 bfd_fatal ("set section flags");
969 /* Copy the section contents. */
972 copy_sections (inbfd, insec, data_ptr)
977 bfd *outbfd = (bfd *) data_ptr;
981 bfd_size_type reloc_size;
983 outsec = insec->output_section;
984 assert (outsec != NULL);
986 size = bfd_get_section_size_before_reloc (insec);
990 /* FIXME: Why are these necessary? */
991 insec->_cooked_size = insec->_raw_size;
992 insec->reloc_done = true;
994 if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
998 contents = xmalloc (size);
999 if (! bfd_get_section_contents (inbfd, insec, contents,
1000 (file_ptr) 0, size))
1001 bfd_fatal (bfd_get_filename (inbfd));
1004 reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
1005 if (reloc_size == 0)
1006 bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
1010 bfd_size_type reloc_count;
1012 relocs = (arelent **) xmalloc (reloc_size);
1013 reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols);
1014 mangle_relocs (outbfd, insec, relocs, &reloc_count, (char *) contents,
1016 bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
1019 if (contents != NULL)
1021 if (! bfd_set_section_contents (outbfd, outsec, contents,
1022 insec->output_offset, size))
1023 bfd_fatal (bfd_get_filename (outbfd));
1028 /* Some, perhaps all, NetWare targets require changing the relocs used
1029 by the input formats. */
1032 mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents, contents_size)
1036 bfd_size_type *reloc_count_ptr;
1038 bfd_size_type contents_size;
1040 switch (bfd_get_arch (outbfd))
1043 i386_mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents,
1051 /* NetWare on the i386 supports a restricted set of relocs, which are
1052 different from those used on other i386 targets. This routine
1053 converts the relocs. It is, obviously, very target dependent. At
1054 the moment, the nlm32-i386 backend performs similar translations;
1055 however, it is more reliable and efficient to do them here. */
1057 static reloc_howto_type nlm_i386_pcrel_howto =
1058 HOWTO (1, /* type */
1060 2, /* size (0 = byte, 1 = short, 2 = long) */
1062 true, /* pc_relative */
1064 complain_overflow_signed, /* complain_on_overflow */
1065 0, /* special_function */
1066 "DISP32", /* name */
1067 true, /* partial_inplace */
1068 0xffffffff, /* src_mask */
1069 0xffffffff, /* dst_mask */
1070 true); /* pcrel_offset */
1073 i386_mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents,
1078 bfd_size_type *reloc_count_ptr;
1080 bfd_size_type contents_size;
1082 bfd_size_type reloc_count, i;
1084 reloc_count = *reloc_count_ptr;
1085 for (i = 0; i < reloc_count; i++)
1089 bfd_size_type address;
1093 sym = *rel->sym_ptr_ptr;
1095 /* We're moving the relocs from the input section to the output
1096 section, so we must adjust the address accordingly. */
1097 address = rel->address;
1098 rel->address += insec->output_offset;
1100 /* Note that no serious harm will ensue if we fail to change a
1101 reloc. The backend will fail when writing out the reloc. */
1103 /* Make sure this reloc is within the data we have. We use only
1104 4 byte relocs here, so we insist on having 4 bytes. */
1105 if (address + 4 > contents_size)
1108 /* A PC relative reloc entirely within a single section is
1109 completely unnecessary. This can be generated by ld -r. */
1110 if (sym == insec->symbol
1111 && rel->howto != NULL
1112 && rel->howto->pc_relative
1113 && ! rel->howto->pcrel_offset)
1117 memmove (relocs, relocs + 1,
1118 (reloc_count - i) * sizeof (arelent *));
1122 /* Get the amount the relocation will add in. */
1123 addend = rel->addend + sym->value;
1125 /* NetWare doesn't support PC relative relocs against defined
1126 symbols, so we have to eliminate them by doing the relocation
1127 now. We can only do this if the reloc is within a single
1129 if (rel->howto != NULL
1130 && rel->howto->pc_relative
1131 && bfd_get_section (sym) == insec->output_section)
1135 if (rel->howto->pcrel_offset)
1138 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1140 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1144 memmove (relocs, relocs + 1,
1145 (reloc_count - i) * sizeof (arelent *));
1149 /* NetWare doesn't support reloc addends, so we get rid of them
1150 here by simply adding them into the object data. We handle
1151 the symbol value, if any, the same way. */
1153 && rel->howto != NULL
1154 && rel->howto->rightshift == 0
1155 && rel->howto->size == 2
1156 && rel->howto->bitsize == 32
1157 && rel->howto->bitpos == 0
1158 && rel->howto->src_mask == 0xffffffff
1159 && rel->howto->dst_mask == 0xffffffff)
1163 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1165 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1167 /* Adjust the reloc for the changes we just made. */
1169 if (bfd_get_section (sym) != &bfd_und_section)
1170 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
1173 /* NetWare uses a reloc with pcrel_offset set. We adjust
1174 pc_relative relocs accordingly. We are going to change the
1175 howto field, so we can only do this if the current one is
1176 compatible. We should check that special_function is NULL
1177 here, but at the moment coff-i386 uses a special_function
1178 which does not affect what we are doing here. */
1179 if (rel->howto != NULL
1180 && rel->howto->pc_relative
1181 && ! rel->howto->pcrel_offset
1182 && rel->howto->rightshift == 0
1183 && rel->howto->size == 2
1184 && rel->howto->bitsize == 32
1185 && rel->howto->bitpos == 0
1186 && rel->howto->src_mask == 0xffffffff
1187 && rel->howto->dst_mask == 0xffffffff)
1191 /* When pcrel_offset is not set, it means that the negative
1192 of the address of the memory location is stored in the
1193 memory location. We must add it back in. */
1194 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1196 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1198 /* We must change to a new howto. */
1199 rel->howto = &nlm_i386_pcrel_howto;