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