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