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