* configure.in: Add -lkernel32 to WIN32LIBADD on cygwin32.
[deliverable/binutils-gdb.git] / binutils / nlmconv.c
1 /* nlmconv.c -- NLM conversion program
2 Copyright (C) 1993, 94, 95, 96, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. */
26
27 /* AIX requires this to be the first thing in the file. */
28 #ifndef __GNUC__
29 # ifdef _AIX
30 #pragma alloca
31 #endif
32 #endif
33
34 #include "bfd.h"
35 #include "libiberty.h"
36 #include "bucomm.h"
37
38 #include <ansidecl.h>
39 #include <time.h>
40 #include <ctype.h>
41 #include <sys/stat.h>
42 #include <sys/file.h>
43 #include <assert.h>
44 #include <getopt.h>
45
46 /* Internal BFD NLM header. */
47 #include "libnlm.h"
48 #include "nlmconv.h"
49
50 #ifdef NLMCONV_ALPHA
51 #include "coff/sym.h"
52 #include "coff/ecoff.h"
53 #endif
54
55 /* If strerror is just a macro, we want to use the one from libiberty
56 since it will handle undefined values. */
57 #undef strerror
58 extern char *strerror ();
59
60 #ifndef localtime
61 extern struct tm *localtime ();
62 #endif
63
64 #ifndef SEEK_SET
65 #define SEEK_SET 0
66 #endif
67
68 #ifndef R_OK
69 #define R_OK 4
70 #define W_OK 2
71 #define X_OK 1
72 #endif
73 \f
74 /* Global variables. */
75
76 /* The name used to invoke the program. */
77 char *program_name;
78
79 /* Local variables. */
80
81 /* Whether to print out debugging information (currently just controls
82 whether it prints the linker command if there is one). */
83 static int debug;
84
85 /* The symbol table. */
86 static asymbol **symbols;
87
88 /* A section we create in the output file to hold pointers to where
89 the sections of the input file end up. We will put a pointer to
90 this section in the NLM header. These is an entry for each input
91 section. The format is
92 null terminated section name
93 zeroes to adjust to 4 byte boundary
94 4 byte section data file pointer
95 4 byte section size
96 We don't need a version number. The way we find this information
97 is by finding a stamp in the NLM header information. If we need to
98 change the format of this information, we can simply change the
99 stamp. */
100 static asection *secsec;
101
102 /* A temporary file name to be unlinked on exit. Actually, for most
103 errors, we leave it around. It's not clear whether that is helpful
104 or not. */
105 static char *unlink_on_exit;
106
107 /* The list of long options. */
108 static struct option long_options[] =
109 {
110 { "debug", no_argument, 0, 'd' },
111 { "header-file", required_argument, 0, 'T' },
112 { "help", no_argument, 0, 'h' },
113 { "input-target", required_argument, 0, 'I' },
114 { "input-format", required_argument, 0, 'I' }, /* Obsolete */
115 { "linker", required_argument, 0, 'l' },
116 { "output-target", required_argument, 0, 'O' },
117 { "output-format", required_argument, 0, 'O' }, /* Obsolete */
118 { "version", no_argument, 0, 'V' },
119 { NULL, no_argument, 0, 0 }
120 };
121
122 /* Local routines. */
123
124 static void show_help PARAMS ((void));
125 static void show_usage PARAMS ((FILE *, int));
126 static const char *select_output_format PARAMS ((enum bfd_architecture,
127 unsigned long, boolean));
128 static void setup_sections PARAMS ((bfd *, asection *, PTR));
129 static void copy_sections PARAMS ((bfd *, asection *, PTR));
130 static void mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
131 long *, char *,
132 bfd_size_type));
133 static void default_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
134 long *, char *,
135 bfd_size_type));
136 static char *link_inputs PARAMS ((struct string_list *, char *));
137
138 #ifdef NLMCONV_I386
139 static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
140 long *, char *,
141 bfd_size_type));
142 #endif
143
144 #ifdef NLMCONV_ALPHA
145 static void alpha_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
146 long *, char *,
147 bfd_size_type));
148 #endif
149
150 #ifdef NLMCONV_POWERPC
151 static void powerpc_build_stubs PARAMS ((bfd *, bfd *, asymbol ***, long *));
152 static void powerpc_resolve_stubs PARAMS ((bfd *, bfd *));
153 static void powerpc_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
154 long *, char *,
155 bfd_size_type));
156 #endif
157 \f
158 /* The main routine. */
159
160 int
161 main (argc, argv)
162 int argc;
163 char **argv;
164 {
165 int opt;
166 char *input_file = NULL;
167 const char *input_format = NULL;
168 const char *output_format = NULL;
169 const char *header_file = NULL;
170 char *ld_arg = NULL;
171 Nlm_Internal_Fixed_Header fixed_hdr_struct;
172 Nlm_Internal_Variable_Header var_hdr_struct;
173 Nlm_Internal_Version_Header version_hdr_struct;
174 Nlm_Internal_Copyright_Header copyright_hdr_struct;
175 Nlm_Internal_Extended_Header extended_hdr_struct;
176 bfd *inbfd;
177 bfd *outbfd;
178 asymbol **newsyms, **outsyms;
179 long symcount, newsymalloc, newsymcount;
180 long symsize;
181 asection *text_sec, *bss_sec, *data_sec;
182 bfd_vma vma;
183 bfd_size_type align;
184 asymbol *endsym;
185 long i;
186 char inlead, outlead;
187 boolean gotstart, gotexit, gotcheck;
188 struct stat st;
189 FILE *custom_data, *help_data, *message_data, *rpc_data, *shared_data;
190 size_t custom_size, help_size, message_size, module_size, rpc_size;
191 asection *custom_section, *help_section, *message_section, *module_section;
192 asection *rpc_section, *shared_section;
193 bfd *sharedbfd;
194 size_t shared_offset, shared_size;
195 Nlm_Internal_Fixed_Header sharedhdr;
196 int len;
197 char *modname;
198 char **matching;
199
200 program_name = argv[0];
201 xmalloc_set_program_name (program_name);
202
203 bfd_init ();
204 set_default_bfd_target ();
205
206 while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options,
207 (int *) NULL))
208 != EOF)
209 {
210 switch (opt)
211 {
212 case 'd':
213 debug = 1;
214 break;
215 case 'h':
216 show_help ();
217 /*NOTREACHED*/
218 case 'I':
219 input_format = optarg;
220 break;
221 case 'l':
222 ld_arg = optarg;
223 break;
224 case 'O':
225 output_format = optarg;
226 break;
227 case 'T':
228 header_file = optarg;
229 break;
230 case 'V':
231 print_version ("nlmconv");
232 /*NOTREACHED*/
233 case 0:
234 break;
235 default:
236 show_usage (stderr, 1);
237 /*NOTREACHED*/
238 }
239 }
240
241 /* The input and output files may be named on the command line. */
242 output_file = NULL;
243 if (optind < argc)
244 {
245 input_file = argv[optind];
246 ++optind;
247 if (optind < argc)
248 {
249 output_file = argv[optind];
250 ++optind;
251 if (optind < argc)
252 show_usage (stderr, 1);
253 if (strcmp (input_file, output_file) == 0)
254 {
255 fprintf (stderr,
256 "%s: input and output files must be different\n",
257 program_name);
258 exit (1);
259 }
260 }
261 }
262
263 /* Initialize the header information to default values. */
264 fixed_hdr = &fixed_hdr_struct;
265 memset ((PTR) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct);
266 var_hdr = &var_hdr_struct;
267 memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct);
268 version_hdr = &version_hdr_struct;
269 memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct);
270 copyright_hdr = &copyright_hdr_struct;
271 memset ((PTR) &copyright_hdr_struct, 0, sizeof copyright_hdr_struct);
272 extended_hdr = &extended_hdr_struct;
273 memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct);
274 check_procedure = NULL;
275 custom_file = NULL;
276 debug_info = false;
277 exit_procedure = "_Stop";
278 export_symbols = NULL;
279 map_file = NULL;
280 full_map = false;
281 help_file = NULL;
282 import_symbols = NULL;
283 message_file = NULL;
284 modules = NULL;
285 sharelib_file = NULL;
286 start_procedure = "_Prelude";
287 verbose = false;
288 rpc_file = NULL;
289
290 parse_errors = 0;
291
292 /* Parse the header file (if there is one). */
293 if (header_file != NULL)
294 {
295 if (! nlmlex_file (header_file)
296 || yyparse () != 0
297 || parse_errors != 0)
298 exit (1);
299 }
300
301 if (input_files != NULL)
302 {
303 if (input_file != NULL)
304 {
305 fprintf (stderr,
306 "%s: input file named both on command line and with INPUT\n",
307 program_name);
308 exit (1);
309 }
310 if (input_files->next == NULL)
311 input_file = input_files->string;
312 else
313 input_file = link_inputs (input_files, ld_arg);
314 }
315 else if (input_file == NULL)
316 {
317 fprintf (stderr, "%s: no input file\n", program_name);
318 show_usage (stderr, 1);
319 }
320
321 inbfd = bfd_openr (input_file, input_format);
322 if (inbfd == NULL)
323 bfd_fatal (input_file);
324
325 if (! bfd_check_format_matches (inbfd, bfd_object, &matching))
326 {
327 bfd_nonfatal (input_file);
328 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
329 {
330 list_matching_formats (matching);
331 free (matching);
332 }
333 exit (1);
334 }
335
336 if (output_format == NULL)
337 output_format = select_output_format (bfd_get_arch (inbfd),
338 bfd_get_mach (inbfd),
339 bfd_big_endian (inbfd));
340
341 assert (output_format != NULL);
342
343 /* Use the output file named on the command line if it exists.
344 Otherwise use the file named in the OUTPUT statement. */
345 if (output_file == NULL)
346 {
347 fprintf (stderr, "%s: no name for output file\n",
348 program_name);
349 show_usage (stderr, 1);
350 }
351
352 outbfd = bfd_openw (output_file, output_format);
353 if (outbfd == NULL)
354 bfd_fatal (output_file);
355 if (! bfd_set_format (outbfd, bfd_object))
356 bfd_fatal (output_file);
357
358 assert (bfd_get_flavour (outbfd) == bfd_target_nlm_flavour);
359
360 if (bfd_arch_get_compatible (inbfd, outbfd) == NULL)
361 fprintf (stderr,
362 "%s: warning:input and output formats are not compatible\n",
363 program_name);
364
365 /* Move the values read from the command file into outbfd. */
366 *nlm_fixed_header (outbfd) = fixed_hdr_struct;
367 *nlm_variable_header (outbfd) = var_hdr_struct;
368 *nlm_version_header (outbfd) = version_hdr_struct;
369 *nlm_copyright_header (outbfd) = copyright_hdr_struct;
370 *nlm_extended_header (outbfd) = extended_hdr_struct;
371
372 /* Start copying the input BFD to the output BFD. */
373 if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd)))
374 bfd_fatal (bfd_get_filename (outbfd));
375
376 symsize = bfd_get_symtab_upper_bound (inbfd);
377 if (symsize < 0)
378 bfd_fatal (input_file);
379 symbols = (asymbol **) xmalloc (symsize);
380 symcount = bfd_canonicalize_symtab (inbfd, symbols);
381 if (symcount < 0)
382 bfd_fatal (input_file);
383
384 /* Make sure we have a .bss section. */
385 bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME);
386 if (bss_sec == NULL)
387 {
388 bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME);
389 if (bss_sec == NULL
390 || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC)
391 || ! bfd_set_section_alignment (outbfd, bss_sec, 1))
392 bfd_fatal ("make .bss section");
393 }
394
395 /* We store the original section names in the .nlmsections section,
396 so that programs which understand it can resurrect the original
397 sections from the NLM. We will put a pointer to .nlmsections in
398 the NLM header area. */
399 secsec = bfd_make_section (outbfd, ".nlmsections");
400 if (secsec == NULL)
401 bfd_fatal ("make .nlmsections section");
402 if (! bfd_set_section_flags (outbfd, secsec, SEC_HAS_CONTENTS))
403 bfd_fatal ("set .nlmsections flags");
404
405 #ifdef NLMCONV_POWERPC
406 /* For PowerPC NetWare we need to build stubs for calls to undefined
407 symbols. Because each stub requires an entry in the TOC section
408 which must be at the same location as other entries in the TOC
409 section, we must do this before determining where the TOC section
410 goes in setup_sections. */
411 if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
412 powerpc_build_stubs (inbfd, outbfd, &symbols, &symcount);
413 #endif
414
415 /* Set up the sections. */
416 bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);
417
418 text_sec = bfd_get_section_by_name (outbfd, NLM_CODE_NAME);
419
420 /* The .bss section immediately follows the .data section. */
421 data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME);
422 if (data_sec != NULL)
423 {
424 bfd_size_type add;
425
426 vma = bfd_get_section_size_before_reloc (data_sec);
427 align = 1 << bss_sec->alignment_power;
428 add = ((vma + align - 1) &~ (align - 1)) - vma;
429 vma += add;
430 if (! bfd_set_section_vma (outbfd, bss_sec, vma))
431 bfd_fatal ("set .bss vma");
432 if (add != 0)
433 {
434 bfd_size_type data_size;
435
436 data_size = bfd_get_section_size_before_reloc (data_sec);
437 if (! bfd_set_section_size (outbfd, data_sec, data_size + add))
438 bfd_fatal ("set .data size");
439 }
440 }
441
442 /* Adjust symbol information. */
443 inlead = bfd_get_symbol_leading_char (inbfd);
444 outlead = bfd_get_symbol_leading_char (outbfd);
445 gotstart = false;
446 gotexit = false;
447 gotcheck = false;
448 newsymalloc = 10;
449 newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *));
450 newsymcount = 0;
451 endsym = NULL;
452 for (i = 0; i < symcount; i++)
453 {
454 register asymbol *sym;
455
456 sym = symbols[i];
457
458 /* Add or remove a leading underscore. */
459 if (inlead != outlead)
460 {
461 if (inlead != '\0')
462 {
463 if (bfd_asymbol_name (sym)[0] == inlead)
464 {
465 if (outlead == '\0')
466 ++sym->name;
467 else
468 {
469 char *new;
470
471 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1);
472 new[0] = outlead;
473 strcpy (new + 1, bfd_asymbol_name (sym) + 1);
474 sym->name = new;
475 }
476 }
477 }
478 else
479 {
480 char *new;
481
482 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2);
483 new[0] = outlead;
484 strcpy (new + 1, bfd_asymbol_name (sym));
485 sym->name = new;
486 }
487 }
488
489 /* NLM's have an uninitialized data section, but they do not
490 have a common section in the Unix sense. Move all common
491 symbols into the .bss section, and mark them as exported. */
492 if (bfd_is_com_section (bfd_get_section (sym)))
493 {
494 bfd_vma size;
495
496 sym->section = bss_sec;
497 size = sym->value;
498 sym->value = bss_sec->_raw_size;
499 bss_sec->_raw_size += size;
500 align = 1 << bss_sec->alignment_power;
501 bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1);
502 sym->flags |= BSF_EXPORT | BSF_GLOBAL;
503 }
504 else if (bfd_get_section (sym)->output_section != NULL)
505 {
506 /* Move the symbol into the output section. */
507 sym->value += bfd_get_section (sym)->output_offset;
508 sym->section = bfd_get_section (sym)->output_section;
509 /* This is no longer a section symbol. */
510 sym->flags &=~ BSF_SECTION_SYM;
511 }
512
513 /* Force _edata and _end to be defined. This would normally be
514 done by the linker, but the manipulation of the common
515 symbols will confuse it. */
516 if ((sym->flags & BSF_DEBUGGING) == 0
517 && bfd_asymbol_name (sym)[0] == '_'
518 && bfd_is_und_section (bfd_get_section (sym)))
519 {
520 if (strcmp (bfd_asymbol_name (sym), "_edata") == 0)
521 {
522 sym->section = bss_sec;
523 sym->value = 0;
524 }
525 if (strcmp (bfd_asymbol_name (sym), "_end") == 0)
526 {
527 sym->section = bss_sec;
528 endsym = sym;
529 }
530
531 #ifdef NLMCONV_POWERPC
532 /* For PowerPC NetWare, we define __GOT0. This is the start
533 of the .got section. */
534 if (bfd_get_arch (inbfd) == bfd_arch_powerpc
535 && strcmp (bfd_asymbol_name (sym), "__GOT0") == 0)
536 {
537 asection *got_sec;
538
539 got_sec = bfd_get_section_by_name (inbfd, ".got");
540 assert (got_sec != (asection *) NULL);
541 sym->value = got_sec->output_offset;
542 sym->section = got_sec->output_section;
543 }
544 #endif
545 }
546
547 /* If this is a global symbol, check the export list. */
548 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0)
549 {
550 register struct string_list *l;
551 int found_simple;
552
553 /* Unfortunately, a symbol can appear multiple times on the
554 export list, with and without prefixes. */
555 found_simple = 0;
556 for (l = export_symbols; l != NULL; l = l->next)
557 {
558 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
559 found_simple = 1;
560 else
561 {
562 char *zbase;
563
564 zbase = strchr (l->string, '@');
565 if (zbase != NULL
566 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
567 {
568 /* We must add a symbol with this prefix. */
569 if (newsymcount >= newsymalloc)
570 {
571 newsymalloc += 10;
572 newsyms = ((asymbol **)
573 xrealloc ((PTR) newsyms,
574 (newsymalloc
575 * sizeof (asymbol *))));
576 }
577 newsyms[newsymcount] =
578 (asymbol *) xmalloc (sizeof (asymbol));
579 *newsyms[newsymcount] = *sym;
580 newsyms[newsymcount]->name = l->string;
581 ++newsymcount;
582 }
583 }
584 }
585 if (! found_simple)
586 {
587 /* The unmodified symbol is actually not exported at
588 all. */
589 sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT);
590 sym->flags |= BSF_LOCAL;
591 }
592 }
593
594 /* If it's an undefined symbol, see if it's on the import list.
595 Change the prefix if necessary. */
596 if (bfd_is_und_section (bfd_get_section (sym)))
597 {
598 register struct string_list *l;
599
600 for (l = import_symbols; l != NULL; l = l->next)
601 {
602 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
603 break;
604 else
605 {
606 char *zbase;
607
608 zbase = strchr (l->string, '@');
609 if (zbase != NULL
610 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
611 {
612 sym->name = l->string;
613 break;
614 }
615 }
616 }
617 if (l == NULL)
618 fprintf (stderr,
619 "%s: warning: symbol %s imported but not in import list\n",
620 program_name, bfd_asymbol_name (sym));
621 }
622
623 /* See if it's one of the special named symbols. */
624 if ((sym->flags & BSF_DEBUGGING) == 0)
625 {
626 bfd_vma val;
627
628 /* FIXME: If these symbols are not in the .text section, we
629 add the .text section size to the value. This may not be
630 correct for all targets. I'm not sure how this should
631 really be handled. */
632 if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0)
633 {
634 val = bfd_asymbol_value (sym);
635 if (bfd_get_section (sym) == data_sec
636 && text_sec != (asection *) NULL)
637 val += bfd_section_size (outbfd, text_sec);
638 if (! bfd_set_start_address (outbfd, val))
639 bfd_fatal ("set start address");
640 gotstart = true;
641 }
642 if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0)
643 {
644 val = bfd_asymbol_value (sym);
645 if (bfd_get_section (sym) == data_sec
646 && text_sec != (asection *) NULL)
647 val += bfd_section_size (outbfd, text_sec);
648 nlm_fixed_header (outbfd)->exitProcedureOffset = val;
649 gotexit = true;
650 }
651 if (check_procedure != NULL
652 && strcmp (bfd_asymbol_name (sym), check_procedure) == 0)
653 {
654 val = bfd_asymbol_value (sym);
655 if (bfd_get_section (sym) == data_sec
656 && text_sec != (asection *) NULL)
657 val += bfd_section_size (outbfd, text_sec);
658 nlm_fixed_header (outbfd)->checkUnloadProcedureOffset = val;
659 gotcheck = true;
660 }
661 }
662 }
663
664 if (endsym != NULL)
665 {
666 endsym->value = bfd_get_section_size_before_reloc (bss_sec);
667
668 /* FIXME: If any relocs referring to _end use inplace addends,
669 then I think they need to be updated. This is handled by
670 i386_mangle_relocs. Is it needed for any other object
671 formats? */
672 }
673
674 if (newsymcount == 0)
675 outsyms = symbols;
676 else
677 {
678 outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1)
679 * sizeof (asymbol *));
680 memcpy (outsyms, symbols, symcount * sizeof (asymbol *));
681 memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *));
682 outsyms[symcount + newsymcount] = NULL;
683 }
684
685 bfd_set_symtab (outbfd, outsyms, symcount + newsymcount);
686
687 if (! gotstart)
688 fprintf (stderr, "%s: warning: START procedure %s not defined\n",
689 program_name, start_procedure);
690 if (! gotexit)
691 fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n",
692 program_name, exit_procedure);
693 if (check_procedure != NULL
694 && ! gotcheck)
695 fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n",
696 program_name, check_procedure);
697
698 /* Add additional sections required for the header information. */
699 if (custom_file != NULL)
700 {
701 custom_data = fopen (custom_file, "r");
702 if (custom_data == NULL
703 || fstat (fileno (custom_data), &st) < 0)
704 {
705 fprintf (stderr, "%s:%s: %s\n", program_name, custom_file,
706 strerror (errno));
707 custom_file = NULL;
708 }
709 else
710 {
711 custom_size = st.st_size;
712 custom_section = bfd_make_section (outbfd, ".nlmcustom");
713 if (custom_section == NULL
714 || ! bfd_set_section_size (outbfd, custom_section, custom_size)
715 || ! bfd_set_section_flags (outbfd, custom_section,
716 SEC_HAS_CONTENTS))
717 bfd_fatal ("custom section");
718 }
719 }
720 if (help_file != NULL)
721 {
722 help_data = fopen (help_file, "r");
723 if (help_data == NULL
724 || fstat (fileno (help_data), &st) < 0)
725 {
726 fprintf (stderr, "%s:%s: %s\n", program_name, help_file,
727 strerror (errno));
728 help_file = NULL;
729 }
730 else
731 {
732 help_size = st.st_size;
733 help_section = bfd_make_section (outbfd, ".nlmhelp");
734 if (help_section == NULL
735 || ! bfd_set_section_size (outbfd, help_section, help_size)
736 || ! bfd_set_section_flags (outbfd, help_section,
737 SEC_HAS_CONTENTS))
738 bfd_fatal ("help section");
739 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
740 }
741 }
742 if (message_file != NULL)
743 {
744 message_data = fopen (message_file, "r");
745 if (message_data == NULL
746 || fstat (fileno (message_data), &st) < 0)
747 {
748 fprintf (stderr, "%s:%s: %s\n", program_name, message_file,
749 strerror (errno));
750 message_file = NULL;
751 }
752 else
753 {
754 message_size = st.st_size;
755 message_section = bfd_make_section (outbfd, ".nlmmessages");
756 if (message_section == NULL
757 || ! bfd_set_section_size (outbfd, message_section, message_size)
758 || ! bfd_set_section_flags (outbfd, message_section,
759 SEC_HAS_CONTENTS))
760 bfd_fatal ("message section");
761 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
762 }
763 }
764 if (modules != NULL)
765 {
766 struct string_list *l;
767
768 module_size = 0;
769 for (l = modules; l != NULL; l = l->next)
770 module_size += strlen (l->string) + 1;
771 module_section = bfd_make_section (outbfd, ".nlmmodules");
772 if (module_section == NULL
773 || ! bfd_set_section_size (outbfd, module_section, module_size)
774 || ! bfd_set_section_flags (outbfd, module_section,
775 SEC_HAS_CONTENTS))
776 bfd_fatal ("module section");
777 }
778 if (rpc_file != NULL)
779 {
780 rpc_data = fopen (rpc_file, "r");
781 if (rpc_data == NULL
782 || fstat (fileno (rpc_data), &st) < 0)
783 {
784 fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file,
785 strerror (errno));
786 rpc_file = NULL;
787 }
788 else
789 {
790 rpc_size = st.st_size;
791 rpc_section = bfd_make_section (outbfd, ".nlmrpc");
792 if (rpc_section == NULL
793 || ! bfd_set_section_size (outbfd, rpc_section, rpc_size)
794 || ! bfd_set_section_flags (outbfd, rpc_section,
795 SEC_HAS_CONTENTS))
796 bfd_fatal ("rpc section");
797 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
798 }
799 }
800 if (sharelib_file != NULL)
801 {
802 sharedbfd = bfd_openr (sharelib_file, output_format);
803 if (sharedbfd == NULL
804 || ! bfd_check_format (sharedbfd, bfd_object))
805 {
806 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
807 bfd_errmsg (bfd_get_error ()));
808 sharelib_file = NULL;
809 }
810 else
811 {
812 sharedhdr = *nlm_fixed_header (sharedbfd);
813 bfd_close (sharedbfd);
814 shared_data = fopen (sharelib_file, "r");
815 if (shared_data == NULL
816 || (fstat (fileno (shared_data), &st) < 0))
817 {
818 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
819 strerror (errno));
820 sharelib_file = NULL;
821 }
822 else
823 {
824 /* If we were clever, we could just copy out the
825 sections of the shared library which we actually
826 need. However, we would have to figure out the sizes
827 of the external and public information, and that can
828 not be done without reading through them. */
829 if (sharedhdr.uninitializedDataSize > 0)
830 {
831 /* There is no place to record this information. */
832 fprintf (stderr,
833 "%s:%s: warning: shared libraries can not have uninitialized data\n",
834 program_name, sharelib_file);
835 }
836 shared_offset = st.st_size;
837 if (shared_offset > sharedhdr.codeImageOffset)
838 shared_offset = sharedhdr.codeImageOffset;
839 if (shared_offset > sharedhdr.dataImageOffset)
840 shared_offset = sharedhdr.dataImageOffset;
841 if (shared_offset > sharedhdr.relocationFixupOffset)
842 shared_offset = sharedhdr.relocationFixupOffset;
843 if (shared_offset > sharedhdr.externalReferencesOffset)
844 shared_offset = sharedhdr.externalReferencesOffset;
845 if (shared_offset > sharedhdr.publicsOffset)
846 shared_offset = sharedhdr.publicsOffset;
847 shared_size = st.st_size - shared_offset;
848 shared_section = bfd_make_section (outbfd, ".nlmshared");
849 if (shared_section == NULL
850 || ! bfd_set_section_size (outbfd, shared_section,
851 shared_size)
852 || ! bfd_set_section_flags (outbfd, shared_section,
853 SEC_HAS_CONTENTS))
854 bfd_fatal ("shared section");
855 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
856 }
857 }
858 }
859
860 /* Check whether a version was given. */
861 if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0)
862 fprintf (stderr, "%s: warning: No version number given\n",
863 program_name);
864
865 /* At least for now, always create an extended header, because that
866 is what NLMLINK does. */
867 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
868
869 strncpy (nlm_cygnus_ext_header (outbfd)->stamp, "CyGnUsEx", 8);
870
871 /* If the date was not given, force it in. */
872 if (nlm_version_header (outbfd)->month == 0
873 && nlm_version_header (outbfd)->day == 0
874 && nlm_version_header (outbfd)->year == 0)
875 {
876 time_t now;
877 struct tm *ptm;
878
879 time (&now);
880 ptm = localtime (&now);
881 nlm_version_header (outbfd)->month = ptm->tm_mon + 1;
882 nlm_version_header (outbfd)->day = ptm->tm_mday;
883 nlm_version_header (outbfd)->year = ptm->tm_year + 1900;
884 strncpy (version_hdr->stamp, "VeRsIoN#", 8);
885 }
886
887 #ifdef NLMCONV_POWERPC
888 /* Resolve the stubs we build for PowerPC NetWare. */
889 if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
890 powerpc_resolve_stubs (inbfd, outbfd);
891 #endif
892
893 /* Copy over the sections. */
894 bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd);
895
896 /* Finish up the header information. */
897 if (custom_file != NULL)
898 {
899 PTR data;
900
901 data = xmalloc (custom_size);
902 if (fread (data, 1, custom_size, custom_data) != custom_size)
903 fprintf (stderr, "%s:%s: read: %s\n", program_name, custom_file,
904 strerror (errno));
905 else
906 {
907 if (! bfd_set_section_contents (outbfd, custom_section, data,
908 (file_ptr) 0, custom_size))
909 bfd_fatal ("custom section");
910 nlm_fixed_header (outbfd)->customDataOffset =
911 custom_section->filepos;
912 nlm_fixed_header (outbfd)->customDataSize = custom_size;
913 }
914 free (data);
915 }
916 if (! debug_info)
917 {
918 /* As a special hack, the backend recognizes a debugInfoOffset
919 of -1 to mean that it should not output any debugging
920 information. This can not be handling by fiddling with the
921 symbol table because exported symbols appear in both the
922 export information and the debugging information. */
923 nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1;
924 }
925 if (map_file != NULL)
926 fprintf (stderr,
927 "%s: warning: MAP and FULLMAP are not supported; try ld -M\n",
928 program_name);
929 if (help_file != NULL)
930 {
931 PTR data;
932
933 data = xmalloc (help_size);
934 if (fread (data, 1, help_size, help_data) != help_size)
935 fprintf (stderr, "%s:%s: read: %s\n", program_name, help_file,
936 strerror (errno));
937 else
938 {
939 if (! bfd_set_section_contents (outbfd, help_section, data,
940 (file_ptr) 0, help_size))
941 bfd_fatal ("help section");
942 nlm_extended_header (outbfd)->helpFileOffset =
943 help_section->filepos;
944 nlm_extended_header (outbfd)->helpFileLength = help_size;
945 }
946 free (data);
947 }
948 if (message_file != NULL)
949 {
950 PTR data;
951
952 data = xmalloc (message_size);
953 if (fread (data, 1, message_size, message_data) != message_size)
954 fprintf (stderr, "%s:%s: read: %s\n", program_name, message_file,
955 strerror (errno));
956 else
957 {
958 if (! bfd_set_section_contents (outbfd, message_section, data,
959 (file_ptr) 0, message_size))
960 bfd_fatal ("message section");
961 nlm_extended_header (outbfd)->messageFileOffset =
962 message_section->filepos;
963 nlm_extended_header (outbfd)->messageFileLength = message_size;
964
965 /* FIXME: Are these offsets correct on all platforms? Are
966 they 32 bits on all platforms? What endianness? */
967 nlm_extended_header (outbfd)->languageID =
968 bfd_h_get_32 (outbfd, (bfd_byte *) data + 106);
969 nlm_extended_header (outbfd)->messageCount =
970 bfd_h_get_32 (outbfd, (bfd_byte *) data + 110);
971 }
972 free (data);
973 }
974 if (modules != NULL)
975 {
976 PTR data;
977 unsigned char *set;
978 struct string_list *l;
979 bfd_size_type c;
980
981 data = xmalloc (module_size);
982 c = 0;
983 set = (unsigned char *) data;
984 for (l = modules; l != NULL; l = l->next)
985 {
986 *set = strlen (l->string);
987 strncpy (set + 1, l->string, *set);
988 set += *set + 1;
989 ++c;
990 }
991 if (! bfd_set_section_contents (outbfd, module_section, data,
992 (file_ptr) 0, module_size))
993 bfd_fatal ("module section");
994 nlm_fixed_header (outbfd)->moduleDependencyOffset =
995 module_section->filepos;
996 nlm_fixed_header (outbfd)->numberOfModuleDependencies = c;
997 }
998 if (rpc_file != NULL)
999 {
1000 PTR data;
1001
1002 data = xmalloc (rpc_size);
1003 if (fread (data, 1, rpc_size, rpc_data) != rpc_size)
1004 fprintf (stderr, "%s:%s: read: %s\n", program_name, rpc_file,
1005 strerror (errno));
1006 else
1007 {
1008 if (! bfd_set_section_contents (outbfd, rpc_section, data,
1009 (file_ptr) 0, rpc_size))
1010 bfd_fatal ("rpc section");
1011 nlm_extended_header (outbfd)->RPCDataOffset =
1012 rpc_section->filepos;
1013 nlm_extended_header (outbfd)->RPCDataLength = rpc_size;
1014 }
1015 free (data);
1016 }
1017 if (sharelib_file != NULL)
1018 {
1019 PTR data;
1020
1021 data = xmalloc (shared_size);
1022 if (fseek (shared_data, shared_offset, SEEK_SET) != 0
1023 || fread (data, 1, shared_size, shared_data) != shared_size)
1024 fprintf (stderr, "%s:%s: read: %s\n", program_name, sharelib_file,
1025 strerror (errno));
1026 else
1027 {
1028 if (! bfd_set_section_contents (outbfd, shared_section, data,
1029 (file_ptr) 0, shared_size))
1030 bfd_fatal ("shared section");
1031 }
1032 nlm_extended_header (outbfd)->sharedCodeOffset =
1033 sharedhdr.codeImageOffset - shared_offset + shared_section->filepos;
1034 nlm_extended_header (outbfd)->sharedCodeLength =
1035 sharedhdr.codeImageSize;
1036 nlm_extended_header (outbfd)->sharedDataOffset =
1037 sharedhdr.dataImageOffset - shared_offset + shared_section->filepos;
1038 nlm_extended_header (outbfd)->sharedDataLength =
1039 sharedhdr.dataImageSize;
1040 nlm_extended_header (outbfd)->sharedRelocationFixupOffset =
1041 (sharedhdr.relocationFixupOffset
1042 - shared_offset
1043 + shared_section->filepos);
1044 nlm_extended_header (outbfd)->sharedRelocationFixupCount =
1045 sharedhdr.numberOfRelocationFixups;
1046 nlm_extended_header (outbfd)->sharedExternalReferenceOffset =
1047 (sharedhdr.externalReferencesOffset
1048 - shared_offset
1049 + shared_section->filepos);
1050 nlm_extended_header (outbfd)->sharedExternalReferenceCount =
1051 sharedhdr.numberOfExternalReferences;
1052 nlm_extended_header (outbfd)->sharedPublicsOffset =
1053 sharedhdr.publicsOffset - shared_offset + shared_section->filepos;
1054 nlm_extended_header (outbfd)->sharedPublicsCount =
1055 sharedhdr.numberOfPublics;
1056 nlm_extended_header (outbfd)->sharedDebugRecordOffset =
1057 sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos;
1058 nlm_extended_header (outbfd)->sharedDebugRecordCount =
1059 sharedhdr.numberOfDebugRecords;
1060 nlm_extended_header (outbfd)->SharedInitializationOffset =
1061 sharedhdr.codeStartOffset;
1062 nlm_extended_header (outbfd)->SharedExitProcedureOffset =
1063 sharedhdr.exitProcedureOffset;
1064 free (data);
1065 }
1066 len = strlen (output_file);
1067 if (len > NLM_MODULE_NAME_SIZE - 2)
1068 len = NLM_MODULE_NAME_SIZE - 2;
1069 nlm_fixed_header (outbfd)->moduleName[0] = len;
1070
1071 strncpy (nlm_fixed_header (outbfd)->moduleName + 1, output_file,
1072 NLM_MODULE_NAME_SIZE - 2);
1073 nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0';
1074 for (modname = nlm_fixed_header (outbfd)->moduleName;
1075 *modname != '\0';
1076 modname++)
1077 if (islower (*modname))
1078 *modname = toupper (*modname);
1079
1080 strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
1081 NLM_OLD_THREAD_NAME_LENGTH);
1082
1083 nlm_cygnus_ext_header (outbfd)->offset = secsec->filepos;
1084 nlm_cygnus_ext_header (outbfd)->length = bfd_section_size (outbfd, secsec);
1085
1086 if (! bfd_close (outbfd))
1087 bfd_fatal (output_file);
1088 if (! bfd_close (inbfd))
1089 bfd_fatal (input_file);
1090
1091 if (unlink_on_exit != NULL)
1092 unlink (unlink_on_exit);
1093
1094 return 0;
1095 }
1096 \f
1097 /* Display a help message and exit. */
1098
1099 static void
1100 show_help ()
1101 {
1102 printf ("%s: Convert an object file into a NetWare Loadable Module\n",
1103 program_name);
1104 show_usage (stdout, 0);
1105 }
1106
1107 /* Show a usage message and exit. */
1108
1109 static void
1110 show_usage (file, status)
1111 FILE *file;
1112 int status;
1113 {
1114 fprintf (file, "\
1115 Usage: %s [-dhV] [-I bfdname] [-O bfdname] [-T header-file] [-l linker]\n\
1116 [--input-target=bfdname] [--output-target=bfdname]\n\
1117 [--header-file=file] [--linker=linker] [--debug]\n\
1118 [--help] [--version]\n\
1119 [in-file [out-file]]\n",
1120 program_name);
1121 if (status == 0)
1122 fprintf (file, "Report bugs to bug-gnu-utils@prep.ai.mit.edu\n");
1123 exit (status);
1124 }
1125 \f
1126 /* Select the output format based on the input architecture, machine,
1127 and endianness. This chooses the appropriate NLM target. */
1128
1129 static const char *
1130 select_output_format (arch, mach, bigendian)
1131 enum bfd_architecture arch;
1132 unsigned long mach;
1133 boolean bigendian;
1134 {
1135 switch (arch)
1136 {
1137 #ifdef NLMCONV_I386
1138 case bfd_arch_i386:
1139 return "nlm32-i386";
1140 #endif
1141 #ifdef NLMCONV_SPARC
1142 case bfd_arch_sparc:
1143 return "nlm32-sparc";
1144 #endif
1145 #ifdef NLMCONV_ALPHA
1146 case bfd_arch_alpha:
1147 return "nlm32-alpha";
1148 #endif
1149 #ifdef NLMCONV_POWERPC
1150 case bfd_arch_powerpc:
1151 return "nlm32-powerpc";
1152 #endif
1153 default:
1154 fprintf (stderr, "%s: support not compiled in for %s\n",
1155 program_name, bfd_printable_arch_mach (arch, mach));
1156 exit (1);
1157 /* Avoid warning. */
1158 return NULL;
1159 }
1160 /*NOTREACHED*/
1161 }
1162 \f
1163 /* The BFD sections are copied in two passes. This function selects
1164 the output section for each input section, and sets up the section
1165 name, size, etc. */
1166
1167 static void
1168 setup_sections (inbfd, insec, data_ptr)
1169 bfd *inbfd;
1170 asection *insec;
1171 PTR data_ptr;
1172 {
1173 bfd *outbfd = (bfd *) data_ptr;
1174 flagword f;
1175 const char *outname;
1176 asection *outsec;
1177 bfd_vma offset;
1178 bfd_size_type align;
1179 bfd_size_type add;
1180 bfd_size_type secsecsize;
1181
1182 f = bfd_get_section_flags (inbfd, insec);
1183 if (f & SEC_CODE)
1184 outname = NLM_CODE_NAME;
1185 else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS))
1186 outname = NLM_INITIALIZED_DATA_NAME;
1187 else if (f & SEC_ALLOC)
1188 outname = NLM_UNINITIALIZED_DATA_NAME;
1189 else
1190 outname = bfd_section_name (inbfd, insec);
1191
1192 outsec = bfd_get_section_by_name (outbfd, outname);
1193 if (outsec == NULL)
1194 {
1195 outsec = bfd_make_section (outbfd, outname);
1196 if (outsec == NULL)
1197 bfd_fatal ("make section");
1198 }
1199
1200 insec->output_section = outsec;
1201
1202 offset = bfd_section_size (outbfd, outsec);
1203 align = 1 << bfd_section_alignment (inbfd, insec);
1204 add = ((offset + align - 1) &~ (align - 1)) - offset;
1205 insec->output_offset = offset + add;
1206
1207 if (! bfd_set_section_size (outbfd, outsec,
1208 (bfd_section_size (outbfd, outsec)
1209 + bfd_section_size (inbfd, insec)
1210 + add)))
1211 bfd_fatal ("set section size");
1212
1213 if ((bfd_section_alignment (inbfd, insec)
1214 > bfd_section_alignment (outbfd, outsec))
1215 && ! bfd_set_section_alignment (outbfd, outsec,
1216 bfd_section_alignment (inbfd, insec)))
1217 bfd_fatal ("set section alignment");
1218
1219 if (! bfd_set_section_flags (outbfd, outsec,
1220 f | bfd_get_section_flags (outbfd, outsec)))
1221 bfd_fatal ("set section flags");
1222
1223 bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
1224
1225 /* For each input section we allocate space for an entry in
1226 .nlmsections. */
1227 secsecsize = bfd_section_size (outbfd, secsec);
1228 secsecsize += strlen (bfd_section_name (inbfd, insec)) + 1;
1229 secsecsize = (secsecsize + 3) &~ 3;
1230 secsecsize += 8;
1231 if (! bfd_set_section_size (outbfd, secsec, secsecsize))
1232 bfd_fatal ("set .nlmsections size");
1233 }
1234
1235 /* Copy the section contents. */
1236
1237 static void
1238 copy_sections (inbfd, insec, data_ptr)
1239 bfd *inbfd;
1240 asection *insec;
1241 PTR data_ptr;
1242 {
1243 static bfd_size_type secsecoff = 0;
1244 bfd *outbfd = (bfd *) data_ptr;
1245 const char *inname;
1246 asection *outsec;
1247 bfd_size_type size;
1248 PTR contents;
1249 long reloc_size;
1250 bfd_byte buf[4];
1251 bfd_size_type add;
1252
1253 inname = bfd_section_name (inbfd, insec);
1254
1255 outsec = insec->output_section;
1256 assert (outsec != NULL);
1257
1258 size = bfd_get_section_size_before_reloc (insec);
1259
1260 /* FIXME: Why are these necessary? */
1261 insec->_cooked_size = insec->_raw_size;
1262 insec->reloc_done = true;
1263
1264 if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
1265 contents = NULL;
1266 else
1267 {
1268 contents = xmalloc (size);
1269 if (! bfd_get_section_contents (inbfd, insec, contents,
1270 (file_ptr) 0, size))
1271 bfd_fatal (bfd_get_filename (inbfd));
1272 }
1273
1274 reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
1275 if (reloc_size < 0)
1276 bfd_fatal (bfd_get_filename (inbfd));
1277 if (reloc_size != 0)
1278 {
1279 arelent **relocs;
1280 long reloc_count;
1281
1282 relocs = (arelent **) xmalloc (reloc_size);
1283 reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols);
1284 if (reloc_count < 0)
1285 bfd_fatal (bfd_get_filename (inbfd));
1286 mangle_relocs (outbfd, insec, &relocs, &reloc_count, (char *) contents,
1287 size);
1288
1289 /* FIXME: refers to internal BFD fields. */
1290 if (outsec->orelocation != (arelent **) NULL)
1291 {
1292 bfd_size_type total_count;
1293 arelent **combined;
1294
1295 total_count = reloc_count + outsec->reloc_count;
1296 combined = (arelent **) xmalloc (total_count * sizeof (arelent *));
1297 memcpy (combined, outsec->orelocation,
1298 outsec->reloc_count * sizeof (arelent *));
1299 memcpy (combined + outsec->reloc_count, relocs,
1300 (size_t) (reloc_count * sizeof (arelent *)));
1301 free (outsec->orelocation);
1302 reloc_count = total_count;
1303 relocs = combined;
1304 }
1305
1306 bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
1307 }
1308
1309 if (contents != NULL)
1310 {
1311 if (! bfd_set_section_contents (outbfd, outsec, contents,
1312 insec->output_offset, size))
1313 bfd_fatal (bfd_get_filename (outbfd));
1314 free (contents);
1315 }
1316
1317 /* Add this section to .nlmsections. */
1318 if (! bfd_set_section_contents (outbfd, secsec, (PTR) inname, secsecoff,
1319 strlen (inname) + 1))
1320 bfd_fatal ("set .nlmsection contents");
1321 secsecoff += strlen (inname) + 1;
1322
1323 add = ((secsecoff + 3) &~ 3) - secsecoff;
1324 if (add != 0)
1325 {
1326 bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
1327 if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, add))
1328 bfd_fatal ("set .nlmsection contents");
1329 secsecoff += add;
1330 }
1331
1332 if (contents != NULL)
1333 bfd_h_put_32 (outbfd, (bfd_vma) outsec->filepos, buf);
1334 else
1335 bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
1336 if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
1337 bfd_fatal ("set .nlmsection contents");
1338 secsecoff += 4;
1339
1340 bfd_h_put_32 (outbfd, (bfd_vma) size, buf);
1341 if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
1342 bfd_fatal ("set .nlmsection contents");
1343 secsecoff += 4;
1344 }
1345
1346 /* Some, perhaps all, NetWare targets require changing the relocs used
1347 by the input formats. */
1348
1349 static void
1350 mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1351 contents_size)
1352 bfd *outbfd;
1353 asection *insec;
1354 arelent ***relocs_ptr;
1355 long *reloc_count_ptr;
1356 char *contents;
1357 bfd_size_type contents_size;
1358 {
1359 switch (bfd_get_arch (outbfd))
1360 {
1361 #ifdef NLMCONV_I386
1362 case bfd_arch_i386:
1363 i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1364 contents, contents_size);
1365 break;
1366 #endif
1367 #ifdef NLMCONV_ALPHA
1368 case bfd_arch_alpha:
1369 alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1370 contents, contents_size);
1371 break;
1372 #endif
1373 #ifdef NLMCONV_POWERPC
1374 case bfd_arch_powerpc:
1375 powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1376 contents, contents_size);
1377 break;
1378 #endif
1379 default:
1380 default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1381 contents, contents_size);
1382 break;
1383 }
1384 }
1385
1386 /* By default all we need to do for relocs is change the address by
1387 the output_offset. */
1388
1389 /*ARGSUSED*/
1390 static void
1391 default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1392 contents_size)
1393 bfd *outbfd;
1394 asection *insec;
1395 arelent ***relocs_ptr;
1396 long *reloc_count_ptr;
1397 char *contents;
1398 bfd_size_type contents_size;
1399 {
1400 if (insec->output_offset != 0)
1401 {
1402 long reloc_count;
1403 register arelent **relocs;
1404 register long i;
1405
1406 reloc_count = *reloc_count_ptr;
1407 relocs = *relocs_ptr;
1408 for (i = 0; i < reloc_count; i++, relocs++)
1409 (*relocs)->address += insec->output_offset;
1410 }
1411 }
1412 \f
1413 #ifdef NLMCONV_I386
1414
1415 /* NetWare on the i386 supports a restricted set of relocs, which are
1416 different from those used on other i386 targets. This routine
1417 converts the relocs. It is, obviously, very target dependent. At
1418 the moment, the nlm32-i386 backend performs similar translations;
1419 however, it is more reliable and efficient to do them here. */
1420
1421 static reloc_howto_type nlm_i386_pcrel_howto =
1422 HOWTO (1, /* type */
1423 0, /* rightshift */
1424 2, /* size (0 = byte, 1 = short, 2 = long) */
1425 32, /* bitsize */
1426 true, /* pc_relative */
1427 0, /* bitpos */
1428 complain_overflow_signed, /* complain_on_overflow */
1429 0, /* special_function */
1430 "DISP32", /* name */
1431 true, /* partial_inplace */
1432 0xffffffff, /* src_mask */
1433 0xffffffff, /* dst_mask */
1434 true); /* pcrel_offset */
1435
1436 static void
1437 i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1438 contents_size)
1439 bfd *outbfd;
1440 asection *insec;
1441 arelent ***relocs_ptr;
1442 long *reloc_count_ptr;
1443 char *contents;
1444 bfd_size_type contents_size;
1445 {
1446 long reloc_count, i;
1447 arelent **relocs;
1448
1449 reloc_count = *reloc_count_ptr;
1450 relocs = *relocs_ptr;
1451 for (i = 0; i < reloc_count; i++)
1452 {
1453 arelent *rel;
1454 asymbol *sym;
1455 bfd_size_type address;
1456 bfd_vma addend;
1457
1458 rel = *relocs++;
1459 sym = *rel->sym_ptr_ptr;
1460
1461 /* We're moving the relocs from the input section to the output
1462 section, so we must adjust the address accordingly. */
1463 address = rel->address;
1464 rel->address += insec->output_offset;
1465
1466 /* Note that no serious harm will ensue if we fail to change a
1467 reloc. The backend will fail when writing out the reloc. */
1468
1469 /* Make sure this reloc is within the data we have. We use only
1470 4 byte relocs here, so we insist on having 4 bytes. */
1471 if (address + 4 > contents_size)
1472 continue;
1473
1474 /* A PC relative reloc entirely within a single section is
1475 completely unnecessary. This can be generated by ld -r. */
1476 if (sym == insec->symbol
1477 && rel->howto != NULL
1478 && rel->howto->pc_relative
1479 && ! rel->howto->pcrel_offset)
1480 {
1481 --*reloc_count_ptr;
1482 --relocs;
1483 memmove (relocs, relocs + 1,
1484 (size_t) ((reloc_count - i) * sizeof (arelent *)));
1485 continue;
1486 }
1487
1488 /* Get the amount the relocation will add in. */
1489 addend = rel->addend + sym->value;
1490
1491 /* NetWare doesn't support PC relative relocs against defined
1492 symbols, so we have to eliminate them by doing the relocation
1493 now. We can only do this if the reloc is within a single
1494 section. */
1495 if (rel->howto != NULL
1496 && rel->howto->pc_relative
1497 && bfd_get_section (sym) == insec->output_section)
1498 {
1499 bfd_vma val;
1500
1501 if (rel->howto->pcrel_offset)
1502 addend -= address;
1503
1504 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1505 val += addend;
1506 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1507
1508 --*reloc_count_ptr;
1509 --relocs;
1510 memmove (relocs, relocs + 1,
1511 (size_t) ((reloc_count - i) * sizeof (arelent *)));
1512 continue;
1513 }
1514
1515 /* NetWare doesn't support reloc addends, so we get rid of them
1516 here by simply adding them into the object data. We handle
1517 the symbol value, if any, the same way. */
1518 if (addend != 0
1519 && rel->howto != NULL
1520 && rel->howto->rightshift == 0
1521 && rel->howto->size == 2
1522 && rel->howto->bitsize == 32
1523 && rel->howto->bitpos == 0
1524 && rel->howto->src_mask == 0xffffffff
1525 && rel->howto->dst_mask == 0xffffffff)
1526 {
1527 bfd_vma val;
1528
1529 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1530 val += addend;
1531 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1532
1533 /* Adjust the reloc for the changes we just made. */
1534 rel->addend = 0;
1535 if (! bfd_is_und_section (bfd_get_section (sym)))
1536 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
1537 }
1538
1539 /* NetWare uses a reloc with pcrel_offset set. We adjust
1540 pc_relative relocs accordingly. We are going to change the
1541 howto field, so we can only do this if the current one is
1542 compatible. We should check that special_function is NULL
1543 here, but at the moment coff-i386 uses a special_function
1544 which does not affect what we are doing here. */
1545 if (rel->howto != NULL
1546 && rel->howto->pc_relative
1547 && ! rel->howto->pcrel_offset
1548 && rel->howto->rightshift == 0
1549 && rel->howto->size == 2
1550 && rel->howto->bitsize == 32
1551 && rel->howto->bitpos == 0
1552 && rel->howto->src_mask == 0xffffffff
1553 && rel->howto->dst_mask == 0xffffffff)
1554 {
1555 bfd_vma val;
1556
1557 /* When pcrel_offset is not set, it means that the negative
1558 of the address of the memory location is stored in the
1559 memory location. We must add it back in. */
1560 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1561 val += address;
1562 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1563
1564 /* We must change to a new howto. */
1565 rel->howto = &nlm_i386_pcrel_howto;
1566 }
1567 }
1568 }
1569
1570 #endif /* NLMCONV_I386 */
1571 \f
1572 #ifdef NLMCONV_ALPHA
1573
1574 /* On the Alpha the first reloc for every section must be a special
1575 relocs which hold the GP address. Also, the first reloc in the
1576 file must be a special reloc which holds the address of the .lita
1577 section. */
1578
1579 static reloc_howto_type nlm32_alpha_nw_howto =
1580 HOWTO (ALPHA_R_NW_RELOC, /* type */
1581 0, /* rightshift */
1582 0, /* size (0 = byte, 1 = short, 2 = long) */
1583 0, /* bitsize */
1584 false, /* pc_relative */
1585 0, /* bitpos */
1586 complain_overflow_dont, /* complain_on_overflow */
1587 0, /* special_function */
1588 "NW_RELOC", /* name */
1589 false, /* partial_inplace */
1590 0, /* src_mask */
1591 0, /* dst_mask */
1592 false); /* pcrel_offset */
1593
1594 /*ARGSUSED*/
1595 static void
1596 alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1597 contents_size)
1598 bfd *outbfd;
1599 asection *insec;
1600 register arelent ***relocs_ptr;
1601 long *reloc_count_ptr;
1602 char *contents;
1603 bfd_size_type contents_size;
1604 {
1605 long old_reloc_count;
1606 arelent **old_relocs;
1607 register arelent **relocs;
1608
1609 old_reloc_count = *reloc_count_ptr;
1610 old_relocs = *relocs_ptr;
1611 relocs = (arelent **) xmalloc ((old_reloc_count + 3) * sizeof (arelent *));
1612 *relocs_ptr = relocs;
1613
1614 if (nlm_alpha_backend_data (outbfd)->lita_address == 0)
1615 {
1616 bfd *inbfd;
1617 asection *lita_section;
1618
1619 inbfd = insec->owner;
1620 lita_section = bfd_get_section_by_name (inbfd, _LITA);
1621 if (lita_section != (asection *) NULL)
1622 {
1623 nlm_alpha_backend_data (outbfd)->lita_address =
1624 bfd_get_section_vma (inbfd, lita_section);
1625 nlm_alpha_backend_data (outbfd)->lita_size =
1626 bfd_section_size (inbfd, lita_section);
1627 }
1628 else
1629 {
1630 /* Avoid outputting this reloc again. */
1631 nlm_alpha_backend_data (outbfd)->lita_address = 4;
1632 }
1633
1634 *relocs = (arelent *) xmalloc (sizeof (arelent));
1635 (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1636 (*relocs)->address = nlm_alpha_backend_data (outbfd)->lita_address;
1637 (*relocs)->addend = nlm_alpha_backend_data (outbfd)->lita_size + 1;
1638 (*relocs)->howto = &nlm32_alpha_nw_howto;
1639 ++relocs;
1640 ++(*reloc_count_ptr);
1641 }
1642
1643 /* Get the GP value from bfd. */
1644 if (nlm_alpha_backend_data (outbfd)->gp == 0)
1645 nlm_alpha_backend_data (outbfd)->gp =
1646 bfd_ecoff_get_gp_value (insec->owner);
1647
1648 *relocs = (arelent *) xmalloc (sizeof (arelent));
1649 (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1650 (*relocs)->address = nlm_alpha_backend_data (outbfd)->gp;
1651 (*relocs)->addend = 0;
1652 (*relocs)->howto = &nlm32_alpha_nw_howto;
1653 ++relocs;
1654 ++(*reloc_count_ptr);
1655
1656 memcpy ((PTR) relocs, (PTR) old_relocs,
1657 (size_t) old_reloc_count * sizeof (arelent *));
1658 relocs[old_reloc_count] = (arelent *) NULL;
1659
1660 free (old_relocs);
1661
1662 if (insec->output_offset != 0)
1663 {
1664 register bfd_size_type i;
1665
1666 for (i = 0; i < old_reloc_count; i++, relocs++)
1667 (*relocs)->address += insec->output_offset;
1668 }
1669 }
1670
1671 #endif /* NLMCONV_ALPHA */
1672 \f
1673 #ifdef NLMCONV_POWERPC
1674
1675 /* We keep a linked list of stubs which we must build. Because BFD
1676 requires us to know the sizes of all sections before we can set the
1677 contents of any, we must figure out which stubs we want to build
1678 before we can actually build any of them. */
1679
1680 struct powerpc_stub
1681 {
1682 /* Next stub in linked list. */
1683 struct powerpc_stub *next;
1684
1685 /* Symbol whose value is the start of the stub. This is a symbol
1686 whose name begins with `.'. */
1687 asymbol *start;
1688
1689 /* Symbol we are going to create a reloc against. This is a symbol
1690 with the same name as START but without the leading `.'. */
1691 asymbol *reloc;
1692
1693 /* The TOC index for this stub. This is the index into the TOC
1694 section at which the reloc is created. */
1695 unsigned int toc_index;
1696 };
1697
1698 /* The linked list of stubs. */
1699
1700 static struct powerpc_stub *powerpc_stubs;
1701
1702 /* This is what a stub looks like. The first instruction will get
1703 adjusted with the correct TOC index. */
1704
1705 static unsigned long powerpc_stub_insns[] =
1706 {
1707 0x81820000, /* lwz r12,0(r2) */
1708 0x90410014, /* stw r2,20(r1) */
1709 0x800c0000, /* lwz r0,0(r12) */
1710 0x804c0004, /* lwz r2,r(r12) */
1711 0x7c0903a6, /* mtctr r0 */
1712 0x4e800420, /* bctr */
1713 0, /* Traceback table. */
1714 0xc8000,
1715 0
1716 };
1717
1718 #define POWERPC_STUB_INSN_COUNT \
1719 (sizeof powerpc_stub_insns / sizeof powerpc_stub_insns[0])
1720
1721 #define POWERPC_STUB_SIZE (4 * POWERPC_STUB_INSN_COUNT)
1722
1723 /* Each stub uses a four byte TOC entry. */
1724 #define POWERPC_STUB_TOC_ENTRY_SIZE (4)
1725
1726 /* The original size of the .got section. */
1727 static bfd_size_type powerpc_initial_got_size;
1728
1729 /* Look for all undefined symbols beginning with `.', and prepare to
1730 build a stub for each one. */
1731
1732 static void
1733 powerpc_build_stubs (inbfd, outbfd, symbols_ptr, symcount_ptr)
1734 bfd *inbfd;
1735 bfd *outbfd;
1736 asymbol ***symbols_ptr;
1737 long *symcount_ptr;
1738 {
1739 asection *stub_sec;
1740 asection *got_sec;
1741 unsigned int got_base;
1742 long i;
1743 long symcount;
1744 long stubcount;
1745
1746 /* Make a section to hold stubs. We don't set SEC_HAS_CONTENTS for
1747 the section to prevent copy_sections from reading from it. */
1748 stub_sec = bfd_make_section (inbfd, ".stubs");
1749 if (stub_sec == (asection *) NULL
1750 || ! bfd_set_section_flags (inbfd, stub_sec,
1751 (SEC_CODE
1752 | SEC_RELOC
1753 | SEC_ALLOC
1754 | SEC_LOAD))
1755 || ! bfd_set_section_alignment (inbfd, stub_sec, 2))
1756 bfd_fatal (".stubs");
1757
1758 /* Get the TOC section, which is named .got. */
1759 got_sec = bfd_get_section_by_name (inbfd, ".got");
1760 if (got_sec == (asection *) NULL)
1761 {
1762 got_sec = bfd_make_section (inbfd, ".got");
1763 if (got_sec == (asection *) NULL
1764 || ! bfd_set_section_flags (inbfd, got_sec,
1765 (SEC_DATA
1766 | SEC_RELOC
1767 | SEC_ALLOC
1768 | SEC_LOAD
1769 | SEC_HAS_CONTENTS))
1770 || ! bfd_set_section_alignment (inbfd, got_sec, 2))
1771 bfd_fatal (".got");
1772 }
1773
1774 powerpc_initial_got_size = bfd_section_size (inbfd, got_sec);
1775 got_base = powerpc_initial_got_size;
1776 got_base = (got_base + 3) &~ 3;
1777
1778 stubcount = 0;
1779
1780 symcount = *symcount_ptr;
1781 for (i = 0; i < symcount; i++)
1782 {
1783 asymbol *sym;
1784 asymbol *newsym;
1785 char *newname;
1786 struct powerpc_stub *item;
1787
1788 sym = (*symbols_ptr)[i];
1789
1790 /* We must make a stub for every undefined symbol whose name
1791 starts with '.'. */
1792 if (bfd_asymbol_name (sym)[0] != '.'
1793 || ! bfd_is_und_section (bfd_get_section (sym)))
1794 continue;
1795
1796 /* Make a new undefined symbol with the same name but without
1797 the leading `.'. */
1798 newsym = (asymbol *) xmalloc (sizeof (asymbol));
1799 *newsym = *sym;
1800 newname = (char *) xmalloc (strlen (bfd_asymbol_name (sym)));
1801 strcpy (newname, bfd_asymbol_name (sym) + 1);
1802 newsym->name = newname;
1803
1804 /* Define the `.' symbol to be in the stub section. */
1805 sym->section = stub_sec;
1806 sym->value = stubcount * POWERPC_STUB_SIZE;
1807 /* We set the BSF_DYNAMIC flag here so that we can check it when
1808 we are mangling relocs. FIXME: This is a hack. */
1809 sym->flags = BSF_LOCAL | BSF_DYNAMIC;
1810
1811 /* Add this stub to the linked list. */
1812 item = (struct powerpc_stub *) xmalloc (sizeof (struct powerpc_stub));
1813 item->start = sym;
1814 item->reloc = newsym;
1815 item->toc_index = got_base + stubcount * POWERPC_STUB_TOC_ENTRY_SIZE;
1816
1817 item->next = powerpc_stubs;
1818 powerpc_stubs = item;
1819
1820 ++stubcount;
1821 }
1822
1823 if (stubcount > 0)
1824 {
1825 asymbol **s;
1826 struct powerpc_stub *l;
1827
1828 /* Add the new symbols we just created to the symbol table. */
1829 *symbols_ptr = (asymbol **) xrealloc ((char *) *symbols_ptr,
1830 ((symcount + stubcount)
1831 * sizeof (asymbol)));
1832 *symcount_ptr += stubcount;
1833 s = &(*symbols_ptr)[symcount];
1834 for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1835 *s++ = l->reloc;
1836
1837 /* Set the size of the .stubs section and increase the size of
1838 the .got section. */
1839 if (! bfd_set_section_size (inbfd, stub_sec,
1840 stubcount * POWERPC_STUB_SIZE)
1841 || ! bfd_set_section_size (inbfd, got_sec,
1842 (got_base
1843 + (stubcount
1844 * POWERPC_STUB_TOC_ENTRY_SIZE))))
1845 bfd_fatal ("stub section sizes");
1846 }
1847 }
1848
1849 /* Resolve all the stubs for PowerPC NetWare. We fill in the contents
1850 of the output section, and create new relocs in the TOC. */
1851
1852 static void
1853 powerpc_resolve_stubs (inbfd, outbfd)
1854 bfd *inbfd;
1855 bfd *outbfd;
1856 {
1857 bfd_byte buf[POWERPC_STUB_SIZE];
1858 unsigned int i;
1859 unsigned int stubcount;
1860 arelent **relocs;
1861 asection *got_sec;
1862 arelent **r;
1863 struct powerpc_stub *l;
1864
1865 if (powerpc_stubs == (struct powerpc_stub *) NULL)
1866 return;
1867
1868 for (i = 0; i < POWERPC_STUB_INSN_COUNT; i++)
1869 bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[i], buf + i * 4);
1870
1871 got_sec = bfd_get_section_by_name (inbfd, ".got");
1872 assert (got_sec != (asection *) NULL);
1873 assert (got_sec->output_section->orelocation == (arelent **) NULL);
1874
1875 stubcount = 0;
1876 for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1877 ++stubcount;
1878 relocs = (arelent **) xmalloc (stubcount * sizeof (arelent *));
1879
1880 r = relocs;
1881 for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1882 {
1883 arelent *reloc;
1884
1885 /* Adjust the first instruction to use the right TOC index. */
1886 bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[0] + l->toc_index, buf);
1887
1888 /* Write this stub out. */
1889 if (! bfd_set_section_contents (outbfd,
1890 bfd_get_section (l->start),
1891 buf,
1892 l->start->value,
1893 POWERPC_STUB_SIZE))
1894 bfd_fatal ("writing stub");
1895
1896 /* Create a new reloc for the TOC entry. */
1897 reloc = (arelent *) xmalloc (sizeof (arelent));
1898 reloc->sym_ptr_ptr = &l->reloc;
1899 reloc->address = l->toc_index + got_sec->output_offset;
1900 reloc->addend = 0;
1901 reloc->howto = bfd_reloc_type_lookup (inbfd, BFD_RELOC_32);
1902
1903 *r++ = reloc;
1904 }
1905
1906 bfd_set_reloc (outbfd, got_sec->output_section, relocs, stubcount);
1907 }
1908
1909 /* Adjust relocation entries for PowerPC NetWare. We do not output
1910 TOC relocations. The object code already contains the offset from
1911 the TOC pointer. When the function is called, the TOC register,
1912 r2, will be set to the correct TOC value, so there is no need for
1913 any further reloc. */
1914
1915 /*ARGSUSED*/
1916 static void
1917 powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1918 contents_size)
1919 bfd *outbfd;
1920 asection *insec;
1921 register arelent ***relocs_ptr;
1922 long *reloc_count_ptr;
1923 char *contents;
1924 bfd_size_type contents_size;
1925 {
1926 reloc_howto_type *toc_howto;
1927 long reloc_count;
1928 register arelent **relocs;
1929 register long i;
1930
1931 toc_howto = bfd_reloc_type_lookup (insec->owner, BFD_RELOC_PPC_TOC16);
1932 if (toc_howto == (reloc_howto_type *) NULL)
1933 abort ();
1934
1935 /* If this is the .got section, clear out all the contents beyond
1936 the initial size. We must do this here because copy_sections is
1937 going to write out whatever we return in the contents field. */
1938 if (strcmp (bfd_get_section_name (insec->owner, insec), ".got") == 0)
1939 memset (contents + powerpc_initial_got_size, 0,
1940 (size_t) (bfd_get_section_size_after_reloc (insec)
1941 - powerpc_initial_got_size));
1942
1943 reloc_count = *reloc_count_ptr;
1944 relocs = *relocs_ptr;
1945 for (i = 0; i < reloc_count; i++)
1946 {
1947 arelent *rel;
1948 asymbol *sym;
1949 bfd_vma sym_value;
1950
1951 rel = *relocs++;
1952 sym = *rel->sym_ptr_ptr;
1953
1954 /* Convert any relocs against the .bss section into relocs
1955 against the .data section. */
1956 if (strcmp (bfd_get_section_name (outbfd, bfd_get_section (sym)),
1957 NLM_UNINITIALIZED_DATA_NAME) == 0)
1958 {
1959 asection *datasec;
1960
1961 datasec = bfd_get_section_by_name (outbfd,
1962 NLM_INITIALIZED_DATA_NAME);
1963 if (datasec != NULL)
1964 {
1965 rel->addend += (bfd_get_section_vma (outbfd,
1966 bfd_get_section (sym))
1967 + sym->value);
1968 rel->sym_ptr_ptr = datasec->symbol_ptr_ptr;
1969 sym = *rel->sym_ptr_ptr;
1970 }
1971 }
1972
1973 /* We must be able to resolve all PC relative relocs at this
1974 point. If we get a branch to an undefined symbol we build a
1975 stub, since NetWare will resolve undefined symbols into a
1976 pointer to a function descriptor. */
1977 if (rel->howto->pc_relative)
1978 {
1979 /* This check for whether a symbol is in the same section as
1980 the reloc will be wrong if there is a PC relative reloc
1981 between two sections both of which were placed in the
1982 same output section. This should not happen. */
1983 if (bfd_get_section (sym) != insec->output_section)
1984 fprintf (stderr, "%s: unresolved PC relative reloc against %s\n",
1985 program_name, bfd_asymbol_name (sym));
1986 else
1987 {
1988 bfd_vma val;
1989
1990 assert (rel->howto->size == 2 && rel->howto->pcrel_offset);
1991 val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address);
1992 val = ((val &~ rel->howto->dst_mask)
1993 | (((val & rel->howto->src_mask)
1994 + (sym->value - rel->address)
1995 + rel->addend)
1996 & rel->howto->dst_mask));
1997 bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
1998
1999 /* If this reloc is against an stubbed symbol and the
2000 next instruction is
2001 cror 31,31,31
2002 then we replace the next instruction with
2003 lwz r2,20(r1)
2004 This reloads the TOC pointer after a stub call. */
2005 if (bfd_asymbol_name (sym)[0] == '.'
2006 && (sym->flags & BSF_DYNAMIC) != 0
2007 && (bfd_get_32 (outbfd,
2008 (bfd_byte *) contents + rel->address + 4)
2009 == 0x4ffffb82)) /* cror 31,31,31 */
2010 bfd_put_32 (outbfd, (bfd_vma) 0x80410014, /* lwz r2,20(r1) */
2011 (bfd_byte *) contents + rel->address + 4);
2012
2013 --*reloc_count_ptr;
2014 --relocs;
2015 memmove (relocs, relocs + 1,
2016 (size_t) ((reloc_count - 1) * sizeof (arelent *)));
2017 continue;
2018 }
2019 }
2020
2021 /* When considering a TOC reloc, we do not want to include the
2022 symbol value. The symbol will be start of the TOC section
2023 (which is named .got). We do want to include the addend. */
2024 if (rel->howto == toc_howto)
2025 sym_value = 0;
2026 else
2027 sym_value = sym->value;
2028
2029 /* If this is a relocation against a symbol with a value, or
2030 there is a reloc addend, we need to update the addend in the
2031 object file. */
2032 if (sym_value + rel->addend != 0)
2033 {
2034 bfd_vma val;
2035
2036 switch (rel->howto->size)
2037 {
2038 case 1:
2039 val = bfd_get_16 (outbfd,
2040 (bfd_byte *) contents + rel->address);
2041 val = ((val &~ rel->howto->dst_mask)
2042 | (((val & rel->howto->src_mask)
2043 + sym_value
2044 + rel->addend)
2045 & rel->howto->dst_mask));
2046 if ((bfd_signed_vma) val < - 0x8000
2047 || (bfd_signed_vma) val >= 0x8000)
2048 fprintf (stderr,
2049 "%s: overflow when adjusting relocation against %s\n",
2050 program_name, bfd_asymbol_name (sym));
2051 bfd_put_16 (outbfd, val, (bfd_byte *) contents + rel->address);
2052 break;
2053
2054 case 2:
2055 val = bfd_get_32 (outbfd,
2056 (bfd_byte *) contents + rel->address);
2057 val = ((val &~ rel->howto->dst_mask)
2058 | (((val & rel->howto->src_mask)
2059 + sym_value
2060 + rel->addend)
2061 & rel->howto->dst_mask));
2062 bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
2063 break;
2064
2065 default:
2066 abort ();
2067 }
2068
2069 if (! bfd_is_und_section (bfd_get_section (sym)))
2070 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
2071 rel->addend = 0;
2072 }
2073
2074 /* Now that we have incorporated the addend, remove any TOC
2075 relocs. */
2076 if (rel->howto == toc_howto)
2077 {
2078 --*reloc_count_ptr;
2079 --relocs;
2080 memmove (relocs, relocs + 1,
2081 (size_t) ((reloc_count - i) * sizeof (arelent *)));
2082 continue;
2083 }
2084
2085 rel->address += insec->output_offset;
2086 }
2087 }
2088
2089 #endif /* NLMCONV_POWERPC */
2090 \f
2091 /* Name of linker. */
2092 #ifndef LD_NAME
2093 #define LD_NAME "ld"
2094 #endif
2095
2096 /* Temporary file name base. */
2097 static char *temp_filename;
2098
2099 /* The user has specified several input files. Invoke the linker to
2100 link them all together, and convert and delete the resulting output
2101 file. */
2102
2103 static char *
2104 link_inputs (inputs, ld)
2105 struct string_list *inputs;
2106 char *ld;
2107 {
2108 size_t c;
2109 struct string_list *q;
2110 char **argv;
2111 size_t i;
2112 int pid;
2113 int status;
2114 char *errfmt;
2115 char *errarg;
2116
2117 c = 0;
2118 for (q = inputs; q != NULL; q = q->next)
2119 ++c;
2120
2121 argv = (char **) alloca ((c + 5) * sizeof(char *));
2122
2123 #ifndef __MSDOS__
2124 if (ld == NULL)
2125 {
2126 char *p;
2127
2128 /* Find the linker to invoke based on how nlmconv was run. */
2129 p = program_name + strlen (program_name);
2130 while (p != program_name)
2131 {
2132 if (p[-1] == '/')
2133 {
2134 ld = (char *) xmalloc (p - program_name + strlen (LD_NAME) + 1);
2135 memcpy (ld, program_name, p - program_name);
2136 strcpy (ld + (p - program_name), LD_NAME);
2137 break;
2138 }
2139 --p;
2140 }
2141 }
2142 #endif
2143
2144 if (ld == NULL)
2145 ld = (char *) LD_NAME;
2146
2147 temp_filename = choose_temp_base ();
2148
2149 unlink_on_exit = xmalloc (strlen (temp_filename) + 3);
2150 sprintf (unlink_on_exit, "%s.O", temp_filename);
2151
2152 argv[0] = ld;
2153 argv[1] = (char *) "-Ur";
2154 argv[2] = (char *) "-o";
2155 argv[3] = unlink_on_exit;
2156 i = 4;
2157 for (q = inputs; q != NULL; q = q->next, i++)
2158 argv[i] = q->string;
2159 argv[i] = NULL;
2160
2161 if (debug)
2162 {
2163 for (i = 0; argv[i] != NULL; i++)
2164 fprintf (stderr, " %s", argv[i]);
2165 fprintf (stderr, "\n");
2166 }
2167
2168 pid = pexecute (ld, argv, program_name, (char *) NULL, &errfmt, &errarg,
2169 PEXECUTE_SEARCH | PEXECUTE_ONE);
2170 if (pid == -1)
2171 {
2172 fprintf (stderr, "%s: execution of %s failed: ", program_name, ld);
2173 fprintf (stderr, errfmt, errarg);
2174 unlink (unlink_on_exit);
2175 exit (1);
2176 }
2177
2178 if (pwait (pid, &status, 0) < 0)
2179 {
2180 perror ("pwait");
2181 unlink (unlink_on_exit);
2182 exit (1);
2183 }
2184
2185 if (status != 0)
2186 {
2187 fprintf (stderr, "%s: Execution of %s failed\n", program_name, ld);
2188 unlink (unlink_on_exit);
2189 exit (1);
2190 }
2191
2192 return unlink_on_exit;
2193 }
This page took 0.076711 seconds and 4 git commands to generate.