06eee8098e68830e9545a80a1f29435faa198137
[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)->SharedInitializationOffset =
833 sharedhdr.codeStartOffset;
834 nlm_extended_header (outbfd)->SharedExitProcedureOffset =
835 sharedhdr.exitProcedureOffset;
836 free (data);
837 }
838 len = strlen (argv[optind + 1]);
839 if (len > NLM_MODULE_NAME_SIZE - 2)
840 len = NLM_MODULE_NAME_SIZE - 2;
841 nlm_fixed_header (outbfd)->moduleName[0] = len;
842
843 strncpy (nlm_fixed_header (outbfd)->moduleName + 1, argv[optind + 1],
844 NLM_MODULE_NAME_SIZE - 2);
845 nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0';
846 for (modname = nlm_fixed_header (outbfd)->moduleName;
847 *modname != '\0';
848 modname++)
849 if (islower (*modname))
850 *modname = toupper (*modname);
851
852 strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
853 NLM_OLD_THREAD_NAME_LENGTH);
854
855 if (! bfd_close (outbfd))
856 bfd_fatal (argv[optind + 1]);
857 if (! bfd_close (inbfd))
858 bfd_fatal (argv[optind]);
859
860 return 0;
861 }
862 \f
863 /* Display a help message and exit. */
864
865 static void
866 show_help ()
867 {
868 printf ("%s: Convert an object file into a NetWare Loadable Module\n",
869 program_name);
870 show_usage (stdout, 0);
871 }
872
873 /* Show a usage message and exit. */
874
875 static void
876 show_usage (file, status)
877 FILE *file;
878 int status;
879 {
880 fprintf (file, "\
881 Usage: %s [-hV] [-I format] [-O format] [-T header-file]\n\
882 [--input-format=format] [--output-format=format]\n\
883 [--header-file=file] [--help] [--version]\n\
884 in-file out-file\n",
885 program_name);
886 exit (status);
887 }
888 \f
889 /* Select the output format based on the input architecture, machine,
890 and endianness. This chooses the appropriate NLM target. */
891
892 static const char *
893 select_output_format (arch, mach, bigendian)
894 enum bfd_architecture arch;
895 long mach;
896 boolean bigendian;
897 {
898 switch (arch)
899 {
900 case bfd_arch_i386:
901 return "nlm32-i386";
902 default:
903 fprintf (stderr, "%s: no default NLM format for %s\n",
904 program_name, bfd_printable_arch_mach (arch, mach));
905 exit (1);
906 /* Avoid warning. */
907 return NULL;
908 }
909 /*NOTREACHED*/
910 }
911 \f
912 /* The BFD sections are copied in two passes. This function selects
913 the output section for each input section, and sets up the section
914 name, size, etc. */
915
916 static void
917 setup_sections (inbfd, insec, data_ptr)
918 bfd *inbfd;
919 asection *insec;
920 PTR data_ptr;
921 {
922 bfd *outbfd = (bfd *) data_ptr;
923 flagword f;
924 const char *outname;
925 asection *outsec;
926
927 f = bfd_get_section_flags (inbfd, insec);
928 if (f & SEC_CODE)
929 outname = NLM_CODE_NAME;
930 else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS))
931 outname = NLM_INITIALIZED_DATA_NAME;
932 else if (f & SEC_ALLOC)
933 outname = NLM_UNINITIALIZED_DATA_NAME;
934 else
935 outname = bfd_section_name (inbfd, insec);
936
937 outsec = bfd_get_section_by_name (outbfd, outname);
938 if (outsec == NULL)
939 {
940 outsec = bfd_make_section (outbfd, outname);
941 if (outsec == NULL)
942 bfd_fatal ("make section");
943 }
944
945 insec->output_section = outsec;
946 insec->output_offset = bfd_section_size (outbfd, outsec);
947
948 if (! bfd_set_section_size (outbfd, outsec,
949 (bfd_section_size (outbfd, outsec)
950 + bfd_section_size (inbfd, insec))))
951 bfd_fatal ("set section size");
952
953 if ((bfd_section_alignment (inbfd, insec)
954 > bfd_section_alignment (outbfd, outsec))
955 && ! bfd_set_section_alignment (outbfd, outsec,
956 bfd_section_alignment (inbfd, insec)))
957 bfd_fatal ("set section alignment");
958
959 if (! bfd_set_section_flags (outbfd, outsec, f))
960 bfd_fatal ("set section flags");
961 }
962
963 /* Copy the section contents. */
964
965 static void
966 copy_sections (inbfd, insec, data_ptr)
967 bfd *inbfd;
968 asection *insec;
969 PTR data_ptr;
970 {
971 bfd *outbfd = (bfd *) data_ptr;
972 asection *outsec;
973 bfd_size_type size;
974 PTR contents;
975 bfd_size_type reloc_size;
976
977 outsec = insec->output_section;
978 assert (outsec != NULL);
979
980 size = bfd_get_section_size_before_reloc (insec);
981 if (size == 0)
982 return;
983
984 /* FIXME: Why are these necessary? */
985 insec->_cooked_size = insec->_raw_size;
986 insec->reloc_done = true;
987
988 if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
989 contents = NULL;
990 else
991 {
992 contents = xmalloc (size);
993 if (! bfd_get_section_contents (inbfd, insec, contents,
994 (file_ptr) 0, size))
995 bfd_fatal (bfd_get_filename (inbfd));
996 }
997
998 reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
999 if (reloc_size == 0)
1000 bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
1001 else
1002 {
1003 arelent **relocs;
1004 bfd_size_type reloc_count;
1005
1006 relocs = (arelent **) xmalloc (reloc_size);
1007 reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols);
1008 mangle_relocs (outbfd, insec, relocs, &reloc_count, (char *) contents,
1009 size);
1010 bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
1011 }
1012
1013 if (contents != NULL)
1014 {
1015 if (! bfd_set_section_contents (outbfd, outsec, contents,
1016 insec->output_offset, size))
1017 bfd_fatal (bfd_get_filename (outbfd));
1018 free (contents);
1019 }
1020 }
1021
1022 /* Some, perhaps all, NetWare targets require changing the relocs used
1023 by the input formats. */
1024
1025 static void
1026 mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents, contents_size)
1027 bfd *outbfd;
1028 asection *insec;
1029 arelent **relocs;
1030 bfd_size_type *reloc_count_ptr;
1031 char *contents;
1032 bfd_size_type contents_size;
1033 {
1034 switch (bfd_get_arch (outbfd))
1035 {
1036 case bfd_arch_i386:
1037 i386_mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents,
1038 contents_size);
1039 break;
1040 default:
1041 break;
1042 }
1043 }
1044
1045 /* NetWare on the i386 supports a restricted set of relocs, which are
1046 different from those used on other i386 targets. This routine
1047 converts the relocs. It is, obviously, very target dependent. At
1048 the moment, the nlm32-i386 backend performs similar translations;
1049 however, it is more reliable and efficient to do them here. */
1050
1051 static reloc_howto_type nlm_i386_pcrel_howto =
1052 HOWTO (1, /* type */
1053 0, /* rightshift */
1054 2, /* size (0 = byte, 1 = short, 2 = long) */
1055 32, /* bitsize */
1056 true, /* pc_relative */
1057 0, /* bitpos */
1058 complain_overflow_signed, /* complain_on_overflow */
1059 0, /* special_function */
1060 "DISP32", /* name */
1061 true, /* partial_inplace */
1062 0xffffffff, /* src_mask */
1063 0xffffffff, /* dst_mask */
1064 true); /* pcrel_offset */
1065
1066 static void
1067 i386_mangle_relocs (outbfd, insec, relocs, reloc_count_ptr, contents,
1068 contents_size)
1069 bfd *outbfd;
1070 asection *insec;
1071 arelent **relocs;
1072 bfd_size_type *reloc_count_ptr;
1073 char *contents;
1074 bfd_size_type contents_size;
1075 {
1076 bfd_size_type reloc_count, i;
1077
1078 reloc_count = *reloc_count_ptr;
1079 for (i = 0; i < reloc_count; i++)
1080 {
1081 arelent *rel;
1082 asymbol *sym;
1083 bfd_vma addend;
1084
1085 rel = *relocs++;
1086 sym = *rel->sym_ptr_ptr;
1087
1088 /* Note that no serious harm will ensue if we fail to change a
1089 reloc. The backend will fail when writing out the reloc. */
1090
1091 /* Make sure this reloc is within the data we have. We use only
1092 4 byte relocs here, so we insist on having 4 bytes. */
1093 if (rel->address + 4 > contents_size)
1094 continue;
1095
1096 /* A PC relative reloc entirely within a single section is
1097 completely unnecessary. This can be generated by ld -r. */
1098 if (sym == insec->symbol
1099 && rel->howto != NULL
1100 && rel->howto->pc_relative
1101 && ! rel->howto->pcrel_offset)
1102 {
1103 --*reloc_count_ptr;
1104 --relocs;
1105 memmove (relocs, relocs + 1,
1106 (reloc_count - i) * sizeof (arelent *));
1107 continue;
1108 }
1109
1110 /* Get the amount the relocation will add in. */
1111 addend = rel->addend + sym->value;
1112
1113 /* NetWare doesn't support PC relative relocs against defined
1114 symbols, so we have to eliminate them by doing the relocation
1115 now. We can only do this if the reloc is within a single
1116 section. */
1117 if (rel->howto != NULL
1118 && rel->howto->pc_relative
1119 && bfd_get_section (sym) == insec->output_section)
1120 {
1121 bfd_vma val;
1122
1123 if (rel->howto->pcrel_offset)
1124 addend -= rel->address;
1125
1126 val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address);
1127 val += addend;
1128 bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
1129
1130 --*reloc_count_ptr;
1131 --relocs;
1132 memmove (relocs, relocs + 1,
1133 (reloc_count - i) * sizeof (arelent *));
1134 continue;
1135 }
1136
1137 /* NetWare doesn't support reloc addends, so we get rid of them
1138 here by simply adding them into the object data. We handle
1139 the symbol value, if any, the same way. */
1140 if (addend != 0
1141 && rel->howto != NULL
1142 && rel->howto->rightshift == 0
1143 && rel->howto->size == 2
1144 && rel->howto->bitsize == 32
1145 && rel->howto->bitpos == 0
1146 && rel->howto->src_mask == 0xffffffff
1147 && rel->howto->dst_mask == 0xffffffff)
1148 {
1149 bfd_vma val;
1150
1151 val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address);
1152 val += addend;
1153 bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
1154
1155 /* Adjust the reloc for the changes we just made. */
1156 rel->addend = 0;
1157 if (bfd_get_section (sym) != &bfd_und_section)
1158 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
1159 }
1160
1161 /* NetWare uses a reloc with pcrel_offset set. We adjust
1162 pc_relative relocs accordingly. We are going to change the
1163 howto field, so we can only do this if the current one is
1164 compatible. We should check that special_function is NULL
1165 here, but at the moment coff-i386 uses a special_function
1166 which does not affect what we are doing here. */
1167 if (rel->howto != NULL
1168 && rel->howto->pc_relative
1169 && ! rel->howto->pcrel_offset
1170 && rel->howto->rightshift == 0
1171 && rel->howto->size == 2
1172 && rel->howto->bitsize == 32
1173 && rel->howto->bitpos == 0
1174 && rel->howto->src_mask == 0xffffffff
1175 && rel->howto->dst_mask == 0xffffffff)
1176 {
1177 bfd_vma val;
1178
1179 /* When pcrel_offset is not set, it means that the negative
1180 of the address of the memory location is stored in the
1181 memory location. We must add it back in. */
1182 val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address);
1183 val += rel->address;
1184 bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
1185
1186 /* We must change to a new howto. */
1187 rel->howto = &nlm_i386_pcrel_howto;
1188 }
1189 }
1190 }
This page took 0.06288 seconds and 4 git commands to generate.