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