* nlmconv.c (debug, unlink_on_exit): New static variables.
[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>
39#include "sysdep.h"
40#include "bucomm.h"
41/* Internal BFD NLM header. */
42#include "libnlm.h"
43#include "nlmconv.h"
44
419093bc
ILT
45/* Needed for Alpha support. */
46#include "coff/sym.h"
47#include "coff/ecoff.h"
48
d92aadfd
ILT
49/* If strerror is just a macro, we want to use the one from libiberty
50 since it will handle undefined values. */
51#undef strerror
52extern char *strerror ();
ef5b5368
ILT
53
54#ifndef localtime
55extern struct tm *localtime ();
56#endif
57
0f6df2ee
ILT
58#ifndef getenv
59extern char *getenv ();
60#endif
61
ef5b5368
ILT
62#ifndef SEEK_SET
63#define SEEK_SET 0
64#endif
0f6df2ee
ILT
65
66#ifndef R_OK
67#define R_OK 4
68#define W_OK 2
69#define X_OK 1
70#endif
d92aadfd
ILT
71\f
72/* Global variables. */
73
74/* The name used to invoke the program. */
75char *program_name;
76
77/* The version number. */
78extern char *program_version;
79
ef5b5368
ILT
80/* Local variables. */
81
0f6df2ee
ILT
82/* Whether to print out debugging information (currently just controls
83 whether it prints the linker command if there is one). */
84static int debug;
85
ef5b5368 86/* The symbol table. */
d92aadfd
ILT
87static asymbol **symbols;
88
0f6df2ee
ILT
89/* A temporary file name to be unlinked on exit. Actually, for most
90 errors, we leave it around. It's not clear whether that is helpful
91 or not. */
92static char *unlink_on_exit;
93
d92aadfd
ILT
94/* The list of long options. */
95static struct option long_options[] =
96{
0f6df2ee 97 { "debug", no_argument, 0, 'd' },
419093bc 98 { "header-file", required_argument, 0, 'T' },
ef5b5368 99 { "help", no_argument, 0, 'h' },
d92aadfd 100 { "input-format", required_argument, 0, 'I' },
0f6df2ee 101 { "linker", required_argument, 0, 'l' },
d92aadfd 102 { "output-format", required_argument, 0, 'O' },
ef5b5368 103 { "version", no_argument, 0, 'V' },
d92aadfd
ILT
104 { NULL, no_argument, 0, 0 }
105};
106
107/* Local routines. */
108
109static void show_help PARAMS ((void));
110static void show_usage PARAMS ((FILE *, int));
111static const char *select_output_format PARAMS ((enum bfd_architecture,
419093bc 112 unsigned long, boolean));
d92aadfd
ILT
113static void setup_sections PARAMS ((bfd *, asection *, PTR));
114static void copy_sections PARAMS ((bfd *, asection *, PTR));
419093bc 115static void mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
ef5b5368 116 bfd_size_type *, char *,
d92aadfd 117 bfd_size_type));
419093bc 118static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
ef5b5368 119 bfd_size_type *, char *,
a30f59a4 120 bfd_size_type));
419093bc
ILT
121static void alpha_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
122 bfd_size_type *, char *,
123 bfd_size_type));
124static void default_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
125 bfd_size_type *, char *,
126 bfd_size_type));
0f6df2ee
ILT
127static char *link_inputs PARAMS ((struct string_list *, char *));
128static const char *choose_temp_base_try PARAMS ((const char *,
129 const char *));
130static void choose_temp_base PARAMS ((void));
131static int pexecute PARAMS ((char *, char *[]));
d92aadfd
ILT
132\f
133/* The main routine. */
134
135int
136main (argc, argv)
137 int argc;
138 char **argv;
139{
140 int opt;
0f6df2ee 141 char *input_file = NULL;
d92aadfd
ILT
142 const char *input_format = NULL;
143 const char *output_format = NULL;
144 const char *header_file = NULL;
0f6df2ee
ILT
145 char *ld_arg = NULL;
146 Nlm_Internal_Fixed_Header fixed_hdr_struct;
147 Nlm_Internal_Variable_Header var_hdr_struct;
148 Nlm_Internal_Version_Header version_hdr_struct;
149 Nlm_Internal_Copyright_Header copyright_hdr_struct;
150 Nlm_Internal_Extended_Header extended_hdr_struct;
d92aadfd
ILT
151 bfd *inbfd;
152 bfd *outbfd;
ef5b5368
ILT
153 asymbol **newsyms, **outsyms;
154 unsigned int symcount, newsymalloc, newsymcount;
90d8edfd
ILT
155 asection *bss_sec, *data_sec;
156 bfd_vma vma;
157 bfd_size_type align;
ef5b5368 158 asymbol *endsym;
d92aadfd
ILT
159 unsigned int i;
160 char inlead, outlead;
161 boolean gotstart, gotexit, gotcheck;
162 struct stat st;
ef5b5368 163 FILE *custom_data, *help_data, *message_data, *rpc_data, *shared_data;
419093bc 164 size_t custom_size, help_size, message_size, module_size, rpc_size;
d92aadfd 165 asection *custom_section, *help_section, *message_section, *module_section;
ef5b5368
ILT
166 asection *rpc_section, *shared_section;
167 bfd *sharedbfd;
419093bc 168 size_t shared_offset, shared_size;
ef5b5368 169 Nlm_Internal_Fixed_Header sharedhdr;
d92aadfd 170 int len;
90d8edfd 171 char *modname;
d92aadfd
ILT
172
173 program_name = argv[0];
174
175 bfd_init ();
176
0f6df2ee
ILT
177 while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options,
178 (int *) NULL))
d92aadfd
ILT
179 != EOF)
180 {
181 switch (opt)
182 {
0f6df2ee
ILT
183 case 'd':
184 debug = 1;
185 break;
ef5b5368 186 case 'h':
d92aadfd
ILT
187 show_help ();
188 /*NOTREACHED*/
189 case 'I':
190 input_format = optarg;
191 break;
0f6df2ee
ILT
192 case 'l':
193 ld_arg = optarg;
194 break;
d92aadfd
ILT
195 case 'O':
196 output_format = optarg;
197 break;
198 case 'T':
199 header_file = optarg;
200 break;
ef5b5368 201 case 'V':
d92aadfd
ILT
202 printf ("GNU %s version %s\n", program_name, program_version);
203 exit (0);
204 /*NOTREACHED*/
205 case 0:
206 break;
207 default:
208 show_usage (stderr, 1);
209 /*NOTREACHED*/
210 }
211 }
212
0f6df2ee
ILT
213 /* The input and output files may be named on the command line. */
214 output_file = NULL;
215 if (optind < argc)
d92aadfd 216 {
0f6df2ee
ILT
217 input_file = argv[optind];
218 ++optind;
219 if (optind < argc)
220 {
221 output_file = argv[optind];
222 ++optind;
223 if (optind < argc)
224 show_usage (stderr, 1);
225 if (strcmp (input_file, output_file) == 0)
226 {
227 fprintf (stderr,
228 "%s: input and output files must be different\n",
229 program_name);
230 exit (1);
231 }
232 }
d92aadfd
ILT
233 }
234
d92aadfd 235 /* Initialize the header information to default values. */
0f6df2ee
ILT
236 fixed_hdr = &fixed_hdr_struct;
237 memset ((PTR) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct);
238 var_hdr = &var_hdr_struct;
239 memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct);
240 version_hdr = &version_hdr_struct;
241 memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct);
242 copyright_hdr = &copyright_hdr_struct;
243 memset ((PTR) &copyright_hdr_struct, 0, sizeof copyright_hdr_struct);
244 extended_hdr = &extended_hdr_struct;
245 memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct);
d92aadfd
ILT
246 check_procedure = NULL;
247 custom_file = NULL;
248 debug_info = false;
249 exit_procedure = "_Stop";
250 export_symbols = NULL;
251 map_file = NULL;
252 full_map = false;
253 help_file = NULL;
254 import_symbols = NULL;
255 message_file = NULL;
256 modules = NULL;
257 sharelib_file = NULL;
258 start_procedure = "_Prelude";
259 verbose = false;
260 rpc_file = NULL;
261
262 parse_errors = 0;
263
264 /* Parse the header file (if there is one). */
265 if (header_file != NULL)
266 {
267 if (! nlmlex_file (header_file)
268 || yyparse () != 0
269 || parse_errors != 0)
270 exit (1);
271 }
272
0f6df2ee
ILT
273 if (input_files != NULL)
274 {
275 if (input_file != NULL)
276 {
277 fprintf (stderr,
278 "%s: input file named both on command line and with INPUT\n",
279 program_name);
280 exit (1);
281 }
282 if (input_files->next == NULL)
283 input_file = input_files->string;
284 else
285 input_file = link_inputs (input_files, ld_arg);
286 }
287 else if (input_file == NULL)
288 {
289 fprintf (stderr, "%s: no input file\n", program_name);
290 show_usage (stderr, 1);
291 }
292
293 inbfd = bfd_openr (input_file, input_format);
294 if (inbfd == NULL)
295 bfd_fatal (input_file);
296
297 if (! bfd_check_format (inbfd, bfd_object))
298 bfd_fatal (input_file);
299
300 if (output_format == NULL)
301 output_format = select_output_format (bfd_get_arch (inbfd),
302 bfd_get_mach (inbfd),
303 inbfd->xvec->byteorder_big_p);
304
305 assert (output_format != NULL);
306
307 /* Use the output file named on the command line if it exists.
308 Otherwise use the file named in the OUTPUT statement. */
309 if (output_file == NULL)
310 {
311 fprintf (stderr, "%s: no name for output file\n",
312 program_name);
313 show_usage (stderr, 1);
314 }
315
316 outbfd = bfd_openw (output_file, output_format);
317 if (outbfd == NULL)
318 bfd_fatal (output_file);
319 if (! bfd_set_format (outbfd, bfd_object))
320 bfd_fatal (output_file);
321
322 assert (outbfd->xvec->flavour == bfd_target_nlm_flavour);
323
324 if (bfd_arch_get_compatible (inbfd, outbfd) == NULL)
325 fprintf (stderr,
326 "%s: warning:input and output formats are not compatible\n",
327 program_name);
328
329 /* Move the values read from the command file into outbfd. */
330 *nlm_fixed_header (outbfd) = fixed_hdr_struct;
331 *nlm_variable_header (outbfd) = var_hdr_struct;
332 *nlm_version_header (outbfd) = version_hdr_struct;
333 *nlm_copyright_header (outbfd) = copyright_hdr_struct;
334 *nlm_extended_header (outbfd) = extended_hdr_struct;
335
d92aadfd
ILT
336 /* Start copying the input BFD to the output BFD. */
337 if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd)))
338 bfd_fatal (bfd_get_filename (outbfd));
339
340 symbols = (asymbol **) xmalloc (get_symtab_upper_bound (inbfd));
341 symcount = bfd_canonicalize_symtab (inbfd, symbols);
342
90d8edfd 343 /* Make sure we have a .bss section. */
ef5b5368
ILT
344 bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME);
345 if (bss_sec == NULL)
346 {
347 bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME);
90d8edfd
ILT
348 if (bss_sec == NULL
349 || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC)
350 || ! bfd_set_section_alignment (outbfd, bss_sec, 1))
ef5b5368 351 bfd_fatal ("make .bss section");
ef5b5368
ILT
352 }
353
354 /* Set up the sections. */
355 bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);
356
90d8edfd
ILT
357 /* The .bss section immediately follows the .data section. */
358 data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME);
359 if (data_sec != NULL)
360 {
361 bfd_size_type add;
362
363 vma = bfd_get_section_size_before_reloc (data_sec);
364 align = 1 << bss_sec->alignment_power;
365 add = ((vma + align - 1) &~ (align - 1)) - vma;
366 vma += add;
367 if (! bfd_set_section_vma (outbfd, bss_sec, vma))
368 bfd_fatal ("set .bss vma");
369 if (add != 0)
370 {
371 bfd_size_type data_size;
372
373 data_size = bfd_get_section_size_before_reloc (data_sec);
374 if (! bfd_set_section_size (outbfd, data_sec, data_size + add))
375 bfd_fatal ("set .data size");
376 }
377 }
378
d92aadfd
ILT
379 /* Adjust symbol information. */
380 inlead = bfd_get_symbol_leading_char (inbfd);
381 outlead = bfd_get_symbol_leading_char (outbfd);
382 gotstart = false;
383 gotexit = false;
384 gotcheck = false;
ef5b5368
ILT
385 newsymalloc = 10;
386 newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *));
387 newsymcount = 0;
388 endsym = NULL;
d92aadfd
ILT
389 for (i = 0; i < symcount; i++)
390 {
391 register asymbol *sym;
392
393 sym = symbols[i];
394
395 /* Add or remove a leading underscore. */
396 if (inlead != outlead)
397 {
398 if (inlead != '\0')
399 {
400 if (bfd_asymbol_name (sym)[0] == inlead)
401 {
402 if (outlead == '\0')
403 ++sym->name;
404 else
405 {
406 char *new;
407
408 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1);
409 new[0] = outlead;
410 strcpy (new + 1, bfd_asymbol_name (sym) + 1);
411 sym->name = new;
412 }
413 }
414 }
415 else
416 {
417 char *new;
418
419 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2);
420 new[0] = outlead;
421 strcpy (new + 1, bfd_asymbol_name (sym));
422 sym->name = new;
423 }
424 }
425
ef5b5368
ILT
426 /* NLM's have an uninitialized data section, but they do not
427 have a common section in the Unix sense. Move all common
428 symbols into the .bss section, and mark them as exported. */
429 if (bfd_is_com_section (bfd_get_section (sym)))
430 {
431 bfd_vma size;
ef5b5368
ILT
432
433 sym->section = bss_sec;
434 size = sym->value;
435 sym->value = bss_sec->_raw_size;
436 bss_sec->_raw_size += size;
437 align = 1 << bss_sec->alignment_power;
438 bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1);
ef5b5368
ILT
439 sym->flags |= BSF_EXPORT | BSF_GLOBAL;
440 }
90d8edfd
ILT
441 else if (bfd_get_section (sym)->output_section != NULL)
442 {
443 /* Move the symbol into the output section. */
444 sym->value += bfd_get_section (sym)->output_offset;
445 sym->section = bfd_get_section (sym)->output_section;
446 /* This is no longer a section symbol. */
447 sym->flags &=~ BSF_SECTION_SYM;
448 }
ef5b5368
ILT
449
450 /* Force _edata and _end to be defined. This would normally be
451 done by the linker, but the manipulation of the common
452 symbols will confuse it. */
453 if (bfd_asymbol_name (sym)[0] == '_'
454 && bfd_get_section (sym) == &bfd_und_section)
455 {
456 if (strcmp (bfd_asymbol_name (sym), "_edata") == 0)
457 {
458 sym->section = bss_sec;
459 sym->value = 0;
460 }
461 if (strcmp (bfd_asymbol_name (sym), "_end") == 0)
462 {
463 sym->section = bss_sec;
464 endsym = sym;
465 }
466 }
467
468 /* If this is a global symbol, check the export list. */
469 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0)
d92aadfd
ILT
470 {
471 register struct string_list *l;
ef5b5368 472 int found_simple;
d92aadfd 473
ef5b5368
ILT
474 /* Unfortunately, a symbol can appear multiple times on the
475 export list, with and without prefixes. */
476 found_simple = 0;
d92aadfd
ILT
477 for (l = export_symbols; l != NULL; l = l->next)
478 {
479 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
ef5b5368 480 found_simple = 1;
d92aadfd
ILT
481 else
482 {
483 char *zbase;
484
485 zbase = strchr (l->string, '@');
486 if (zbase != NULL
487 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
488 {
ef5b5368
ILT
489 /* We must add a symbol with this prefix. */
490 if (newsymcount >= newsymalloc)
491 {
492 newsymalloc += 10;
493 newsyms = ((asymbol **)
494 xrealloc (newsyms,
495 (newsymalloc
496 * sizeof (asymbol *))));
497 }
498 newsyms[newsymcount] =
499 (asymbol *) xmalloc (sizeof (asymbol));
500 *newsyms[newsymcount] = *sym;
501 newsyms[newsymcount]->name = l->string;
502 ++newsymcount;
d92aadfd
ILT
503 }
504 }
505 }
ef5b5368
ILT
506 if (! found_simple)
507 {
508 /* The unmodified symbol is actually not exported at
509 all. */
510 sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT);
511 sym->flags |= BSF_LOCAL;
512 }
d92aadfd
ILT
513 }
514
515 /* If it's an undefined symbol, see if it's on the import list.
516 Change the prefix if necessary. */
517 if (bfd_get_section (sym) == &bfd_und_section
518 && import_symbols != NULL)
519 {
520 register struct string_list *l;
521
522 for (l = import_symbols; l != NULL; l = l->next)
523 {
524 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
525 break;
526 else
527 {
528 char *zbase;
529
530 zbase = strchr (l->string, '@');
531 if (zbase != NULL
532 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
533 {
534 sym->name = l->string;
535 break;
536 }
537 }
538 }
539 if (l == NULL)
540 fprintf (stderr,
541 "%s: warning: symbol %s imported but not in import list\n",
542 program_name, bfd_asymbol_name (sym));
543 }
544
545 /* See if it's one of the special named symbols. */
546 if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0)
547 {
548 if (! bfd_set_start_address (outbfd, bfd_asymbol_value (sym)))
549 bfd_fatal ("set start address");
550 gotstart = true;
551 }
552 if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0)
553 {
554 nlm_fixed_header (outbfd)->exitProcedureOffset =
555 bfd_asymbol_value (sym);
556 gotexit = true;
557 }
558 if (check_procedure != NULL
559 && strcmp (bfd_asymbol_name (sym), check_procedure) == 0)
560 {
561 nlm_fixed_header (outbfd)->checkUnloadProcedureOffset =
562 bfd_asymbol_value (sym);
563 gotcheck = true;
564 }
565 }
566
ef5b5368 567 if (endsym != NULL)
90d8edfd 568 endsym->value = bfd_get_section_size_before_reloc (bss_sec);
ef5b5368
ILT
569
570 if (newsymcount == 0)
571 outsyms = symbols;
572 else
573 {
574 outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1)
575 * sizeof (asymbol *));
576 memcpy (outsyms, symbols, symcount * sizeof (asymbol *));
577 memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *));
578 outsyms[symcount + newsymcount] = NULL;
579 }
580
581 bfd_set_symtab (outbfd, outsyms, symcount + newsymcount);
d92aadfd
ILT
582
583 if (! gotstart)
584 fprintf (stderr, "%s: warning: START procedure %s not defined\n",
585 program_name, start_procedure);
586 if (! gotexit)
587 fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n",
588 program_name, exit_procedure);
589 if (check_procedure != NULL
590 && ! gotcheck)
591 fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n",
592 program_name, check_procedure);
593
d92aadfd
ILT
594 /* Add additional sections required for the header information. */
595 if (custom_file != NULL)
596 {
597 custom_data = fopen (custom_file, "r");
598 if (custom_data == NULL
599 || fstat (fileno (custom_data), &st) < 0)
600 {
601 fprintf (stderr, "%s:%s: %s\n", program_name, custom_file,
602 strerror (errno));
603 custom_file = NULL;
604 }
605 else
606 {
607 custom_size = st.st_size;
608 custom_section = bfd_make_section (outbfd, ".nlmcustom");
609 if (custom_section == NULL
610 || ! bfd_set_section_size (outbfd, custom_section, custom_size)
611 || ! bfd_set_section_flags (outbfd, custom_section,
612 SEC_HAS_CONTENTS))
613 bfd_fatal ("custom section");
614 }
615 }
616 if (help_file != NULL)
617 {
618 help_data = fopen (help_file, "r");
619 if (help_data == NULL
620 || fstat (fileno (help_data), &st) < 0)
621 {
622 fprintf (stderr, "%s:%s: %s\n", program_name, help_file,
623 strerror (errno));
624 help_file = NULL;
625 }
626 else
627 {
628 help_size = st.st_size;
629 help_section = bfd_make_section (outbfd, ".nlmhelp");
630 if (help_section == NULL
631 || ! bfd_set_section_size (outbfd, help_section, help_size)
632 || ! bfd_set_section_flags (outbfd, help_section,
633 SEC_HAS_CONTENTS))
634 bfd_fatal ("help section");
635 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
636 }
637 }
638 if (message_file != NULL)
639 {
640 message_data = fopen (message_file, "r");
641 if (message_data == NULL
642 || fstat (fileno (message_data), &st) < 0)
643 {
644 fprintf (stderr, "%s:%s: %s\n", program_name, message_file,
645 strerror (errno));
646 message_file = NULL;
647 }
648 else
649 {
650 message_size = st.st_size;
651 message_section = bfd_make_section (outbfd, ".nlmmessages");
652 if (message_section == NULL
653 || ! bfd_set_section_size (outbfd, message_section, message_size)
654 || ! bfd_set_section_flags (outbfd, message_section,
655 SEC_HAS_CONTENTS))
656 bfd_fatal ("message section");
657 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
658 }
659 }
660 if (modules != NULL)
661 {
662 struct string_list *l;
663
664 module_size = 0;
665 for (l = modules; l != NULL; l = l->next)
666 module_size += strlen (l->string) + 1;
667 module_section = bfd_make_section (outbfd, ".nlmmodules");
668 if (module_section == NULL
669 || ! bfd_set_section_size (outbfd, module_section, module_size)
670 || ! bfd_set_section_flags (outbfd, module_section,
671 SEC_HAS_CONTENTS))
672 bfd_fatal ("module section");
673 }
674 if (rpc_file != NULL)
675 {
676 rpc_data = fopen (rpc_file, "r");
677 if (rpc_data == NULL
678 || fstat (fileno (rpc_data), &st) < 0)
679 {
680 fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file,
681 strerror (errno));
682 rpc_file = NULL;
683 }
684 else
685 {
686 rpc_size = st.st_size;
687 rpc_section = bfd_make_section (outbfd, ".nlmrpc");
688 if (rpc_section == NULL
689 || ! bfd_set_section_size (outbfd, rpc_section, rpc_size)
690 || ! bfd_set_section_flags (outbfd, rpc_section,
691 SEC_HAS_CONTENTS))
692 bfd_fatal ("rpc section");
693 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
694 }
695 }
ef5b5368
ILT
696 if (sharelib_file != NULL)
697 {
698 sharedbfd = bfd_openr (sharelib_file, output_format);
699 if (sharedbfd == NULL
700 || ! bfd_check_format (sharedbfd, bfd_object))
701 {
702 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
703 bfd_errmsg (bfd_error));
704 sharelib_file = NULL;
705 }
706 else
707 {
708 sharedhdr = *nlm_fixed_header (sharedbfd);
709 bfd_close (sharedbfd);
710 shared_data = fopen (sharelib_file, "r");
711 if (shared_data == NULL
712 || (fstat (fileno (shared_data), &st) < 0))
713 {
714 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
715 strerror (errno));
716 sharelib_file = NULL;
717 }
718 else
719 {
720 /* If we were clever, we could just copy out the
721 sections of the shared library which we actually
722 need. However, we would have to figure out the sizes
723 of the external and public information, and that can
724 not be done without reading through them. */
725 shared_offset = st.st_size;
726 if (shared_offset > sharedhdr.codeImageOffset)
727 shared_offset = sharedhdr.codeImageOffset;
728 if (shared_offset > sharedhdr.dataImageOffset)
729 shared_offset = sharedhdr.dataImageOffset;
730 if (shared_offset > sharedhdr.relocationFixupOffset)
731 shared_offset = sharedhdr.relocationFixupOffset;
732 if (shared_offset > sharedhdr.externalReferencesOffset)
733 shared_offset = sharedhdr.externalReferencesOffset;
734 if (shared_offset > sharedhdr.publicsOffset)
735 shared_offset = sharedhdr.publicsOffset;
736 shared_size = st.st_size - shared_offset;
737 shared_section = bfd_make_section (outbfd, ".nlmshared");
738 if (shared_section == NULL
739 || ! bfd_set_section_size (outbfd, shared_section,
740 shared_size)
741 || ! bfd_set_section_flags (outbfd, shared_section,
742 SEC_HAS_CONTENTS))
743 bfd_fatal ("shared section");
744 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
745 }
746 }
747 }
748
749 /* Check whether a version was given. */
750 if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0)
751 fprintf (stderr, "%s: warning: No version number given\n",
752 program_name);
753
754 /* At least for now, always create an extended header, because that
755 is what NLMLINK does. */
756 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
757
758 /* If the date was not given, force it in. */
759 if (nlm_version_header (outbfd)->month == 0
760 && nlm_version_header (outbfd)->day == 0
761 && nlm_version_header (outbfd)->year == 0)
762 {
90d8edfd 763 time_t now;
ef5b5368
ILT
764 struct tm *ptm;
765
766 time (&now);
767 ptm = localtime (&now);
768 nlm_version_header (outbfd)->month = ptm->tm_mon + 1;
769 nlm_version_header (outbfd)->day = ptm->tm_mday;
770 nlm_version_header (outbfd)->year = ptm->tm_year + 1900;
771 strncpy (version_hdr->stamp, "VeRsIoN#", 8);
772 }
d92aadfd
ILT
773
774 /* Copy over the sections. */
775 bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd);
776
777 /* Finish up the header information. */
778 if (custom_file != NULL)
779 {
780 PTR data;
781
782 data = xmalloc (custom_size);
783 if (fread (data, 1, custom_size, custom_data) != custom_size)
784 fprintf (stderr, "%s:%s: read: %s\n", program_name, custom_file,
785 strerror (errno));
786 else
787 {
788 if (! bfd_set_section_contents (outbfd, custom_section, data,
789 (file_ptr) 0, custom_size))
790 bfd_fatal ("custom section");
791 nlm_fixed_header (outbfd)->customDataOffset =
792 custom_section->filepos;
793 nlm_fixed_header (outbfd)->customDataSize = custom_size;
794 }
795 free (data);
796 }
797 if (! debug_info)
798 {
799 /* As a special hack, the backend recognizes a debugInfoOffset
800 of -1 to mean that it should not output any debugging
801 information. This can not be handling by fiddling with the
802 symbol table because exported symbols appear in both the
803 export information and the debugging information. */
804 nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1;
805 }
806 if (map_file != NULL)
807 fprintf (stderr,
808 "%s: MAP and FULLMAP are not supported; try ld -M\n",
809 program_name);
810 if (help_file != NULL)
811 {
812 PTR data;
813
814 data = xmalloc (help_size);
815 if (fread (data, 1, help_size, help_data) != help_size)
816 fprintf (stderr, "%s:%s: read: %s\n", program_name, help_file,
817 strerror (errno));
818 else
819 {
820 if (! bfd_set_section_contents (outbfd, help_section, data,
821 (file_ptr) 0, help_size))
822 bfd_fatal ("help section");
823 nlm_extended_header (outbfd)->helpFileOffset =
824 help_section->filepos;
825 nlm_extended_header (outbfd)->helpFileLength = help_size;
826 }
827 free (data);
828 }
829 if (message_file != NULL)
830 {
831 PTR data;
832
833 data = xmalloc (message_size);
834 if (fread (data, 1, message_size, message_data) != message_size)
835 fprintf (stderr, "%s:%s: read: %s\n", program_name, message_file,
836 strerror (errno));
837 else
838 {
839 if (! bfd_set_section_contents (outbfd, message_section, data,
840 (file_ptr) 0, message_size))
841 bfd_fatal ("message section");
842 nlm_extended_header (outbfd)->messageFileOffset =
843 message_section->filepos;
844 nlm_extended_header (outbfd)->messageFileLength = message_size;
845
846 /* FIXME: Are these offsets correct on all platforms? Are
847 they 32 bits on all platforms? What endianness? */
848 nlm_extended_header (outbfd)->languageID =
849 bfd_h_get_32 (outbfd, (bfd_byte *) data + 106);
850 nlm_extended_header (outbfd)->messageCount =
851 bfd_h_get_32 (outbfd, (bfd_byte *) data + 110);
852 }
853 free (data);
854 }
855 if (modules != NULL)
856 {
857 PTR data;
419093bc 858 unsigned char *set;
d92aadfd
ILT
859 struct string_list *l;
860 bfd_size_type c;
861
862 data = xmalloc (module_size);
863 c = 0;
419093bc 864 set = (unsigned char *) data;
d92aadfd
ILT
865 for (l = modules; l != NULL; l = l->next)
866 {
867 *set = strlen (l->string);
868 strncpy (set + 1, l->string, *set);
869 set += *set + 1;
870 ++c;
871 }
872 if (! bfd_set_section_contents (outbfd, module_section, data,
873 (file_ptr) 0, module_size))
874 bfd_fatal ("module section");
875 nlm_fixed_header (outbfd)->moduleDependencyOffset =
876 module_section->filepos;
877 nlm_fixed_header (outbfd)->numberOfModuleDependencies = c;
878 }
879 if (rpc_file != NULL)
880 {
881 PTR data;
882
883 data = xmalloc (rpc_size);
884 if (fread (data, 1, rpc_size, rpc_data) != rpc_size)
885 fprintf (stderr, "%s:%s: read: %s\n", program_name, rpc_file,
886 strerror (errno));
887 else
888 {
889 if (! bfd_set_section_contents (outbfd, rpc_section, data,
890 (file_ptr) 0, rpc_size))
891 bfd_fatal ("rpc section");
892 nlm_extended_header (outbfd)->RPCDataOffset =
893 rpc_section->filepos;
894 nlm_extended_header (outbfd)->RPCDataLength = rpc_size;
895 }
896 free (data);
897 }
ef5b5368
ILT
898 if (sharelib_file != NULL)
899 {
900 PTR data;
901
902 data = xmalloc (shared_size);
903 if (fseek (shared_data, shared_offset, SEEK_SET) != 0
904 || fread (data, 1, shared_size, shared_data) != shared_size)
905 fprintf (stderr, "%s:%s: read: %s\n", program_name, sharelib_file,
906 strerror (errno));
907 else
908 {
909 if (! bfd_set_section_contents (outbfd, shared_section, data,
910 (file_ptr) 0, shared_size))
911 bfd_fatal ("shared section");
912 }
913 nlm_extended_header (outbfd)->sharedCodeOffset =
914 sharedhdr.codeImageOffset - shared_offset + shared_section->filepos;
915 nlm_extended_header (outbfd)->sharedCodeLength =
916 sharedhdr.codeImageSize;
917 nlm_extended_header (outbfd)->sharedDataOffset =
918 sharedhdr.dataImageOffset - shared_offset + shared_section->filepos;
919 nlm_extended_header (outbfd)->sharedDataLength =
920 sharedhdr.dataImageSize;
921 nlm_extended_header (outbfd)->sharedRelocationFixupOffset =
922 (sharedhdr.relocationFixupOffset
923 - shared_offset
924 + shared_section->filepos);
925 nlm_extended_header (outbfd)->sharedRelocationFixupCount =
926 sharedhdr.numberOfRelocationFixups;
927 nlm_extended_header (outbfd)->sharedExternalReferenceOffset =
928 (sharedhdr.externalReferencesOffset
929 - shared_offset
930 + shared_section->filepos);
931 nlm_extended_header (outbfd)->sharedExternalReferenceCount =
932 sharedhdr.numberOfExternalReferences;
933 nlm_extended_header (outbfd)->sharedPublicsOffset =
934 sharedhdr.publicsOffset - shared_offset + shared_section->filepos;
935 nlm_extended_header (outbfd)->sharedPublicsCount =
936 sharedhdr.numberOfPublics;
a30f59a4
ILT
937 nlm_extended_header (outbfd)->sharedDebugRecordOffset =
938 sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos;
939 nlm_extended_header (outbfd)->sharedDebugRecordCount =
940 sharedhdr.numberOfDebugRecords;
ef5b5368
ILT
941 nlm_extended_header (outbfd)->SharedInitializationOffset =
942 sharedhdr.codeStartOffset;
943 nlm_extended_header (outbfd)->SharedExitProcedureOffset =
944 sharedhdr.exitProcedureOffset;
945 free (data);
946 }
0f6df2ee 947 len = strlen (output_file);
d92aadfd
ILT
948 if (len > NLM_MODULE_NAME_SIZE - 2)
949 len = NLM_MODULE_NAME_SIZE - 2;
950 nlm_fixed_header (outbfd)->moduleName[0] = len;
90d8edfd 951
0f6df2ee 952 strncpy (nlm_fixed_header (outbfd)->moduleName + 1, output_file,
d92aadfd
ILT
953 NLM_MODULE_NAME_SIZE - 2);
954 nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0';
90d8edfd
ILT
955 for (modname = nlm_fixed_header (outbfd)->moduleName;
956 *modname != '\0';
957 modname++)
958 if (islower (*modname))
959 *modname = toupper (*modname);
960
d92aadfd
ILT
961 strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
962 NLM_OLD_THREAD_NAME_LENGTH);
963
964 if (! bfd_close (outbfd))
0f6df2ee 965 bfd_fatal (output_file);
d92aadfd 966 if (! bfd_close (inbfd))
0f6df2ee
ILT
967 bfd_fatal (input_file);
968
969 if (unlink_on_exit != NULL)
970 unlink (unlink_on_exit);
d92aadfd
ILT
971
972 return 0;
973}
974\f
975/* Display a help message and exit. */
976
977static void
978show_help ()
979{
980 printf ("%s: Convert an object file into a NetWare Loadable Module\n",
981 program_name);
982 show_usage (stdout, 0);
983}
984
985/* Show a usage message and exit. */
986
987static void
988show_usage (file, status)
989 FILE *file;
990 int status;
991{
992 fprintf (file, "\
0f6df2ee 993Usage: %s [-dhV] [-I format] [-O format] [-T header-file] [-l linker]\n\
d92aadfd 994 [--input-format=format] [--output-format=format]\n\
0f6df2ee
ILT
995 [--header-file=file] [--linker=linker] [--debug]\n\
996 [--help] [--version]\n\
997 [in-file [out-file]]\n",
d92aadfd
ILT
998 program_name);
999 exit (status);
1000}
1001\f
1002/* Select the output format based on the input architecture, machine,
1003 and endianness. This chooses the appropriate NLM target. */
1004
1005static const char *
1006select_output_format (arch, mach, bigendian)
1007 enum bfd_architecture arch;
419093bc 1008 unsigned long mach;
d92aadfd
ILT
1009 boolean bigendian;
1010{
1011 switch (arch)
1012 {
1013 case bfd_arch_i386:
1014 return "nlm32-i386";
a30f59a4
ILT
1015 case bfd_arch_sparc:
1016 return "nlm32-sparc";
419093bc
ILT
1017 case bfd_arch_alpha:
1018 return "nlm32-alpha";
d92aadfd
ILT
1019 default:
1020 fprintf (stderr, "%s: no default NLM format for %s\n",
1021 program_name, bfd_printable_arch_mach (arch, mach));
1022 exit (1);
1023 /* Avoid warning. */
1024 return NULL;
1025 }
1026 /*NOTREACHED*/
1027}
1028\f
90d8edfd
ILT
1029/* The BFD sections are copied in two passes. This function selects
1030 the output section for each input section, and sets up the section
1031 name, size, etc. */
d92aadfd
ILT
1032
1033static void
1034setup_sections (inbfd, insec, data_ptr)
1035 bfd *inbfd;
1036 asection *insec;
1037 PTR data_ptr;
1038{
1039 bfd *outbfd = (bfd *) data_ptr;
ef5b5368 1040 flagword f;
90d8edfd
ILT
1041 const char *outname;
1042 asection *outsec;
d92aadfd 1043
419093bc
ILT
1044 /* FIXME: We don't want to copy the .reginfo section of an ECOFF
1045 file. However, I don't have a good way to describe this section.
1046 We do want to copy the section when using objcopy. */
1047 if (bfd_get_flavour (inbfd) == bfd_target_ecoff_flavour
1048 && strcmp (bfd_section_name (inbfd, insec), ".reginfo") == 0)
1049 return;
1050
90d8edfd
ILT
1051 f = bfd_get_section_flags (inbfd, insec);
1052 if (f & SEC_CODE)
1053 outname = NLM_CODE_NAME;
1054 else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS))
1055 outname = NLM_INITIALIZED_DATA_NAME;
1056 else if (f & SEC_ALLOC)
1057 outname = NLM_UNINITIALIZED_DATA_NAME;
1058 else
1059 outname = bfd_section_name (inbfd, insec);
1060
1061 outsec = bfd_get_section_by_name (outbfd, outname);
d92aadfd
ILT
1062 if (outsec == NULL)
1063 {
90d8edfd 1064 outsec = bfd_make_section (outbfd, outname);
d92aadfd
ILT
1065 if (outsec == NULL)
1066 bfd_fatal ("make section");
1067 }
1068
1069 insec->output_section = outsec;
90d8edfd 1070 insec->output_offset = bfd_section_size (outbfd, outsec);
d92aadfd
ILT
1071
1072 if (! bfd_set_section_size (outbfd, outsec,
90d8edfd
ILT
1073 (bfd_section_size (outbfd, outsec)
1074 + bfd_section_size (inbfd, insec))))
d92aadfd
ILT
1075 bfd_fatal ("set section size");
1076
90d8edfd
ILT
1077 if ((bfd_section_alignment (inbfd, insec)
1078 > bfd_section_alignment (outbfd, outsec))
1079 && ! bfd_set_section_alignment (outbfd, outsec,
1080 bfd_section_alignment (inbfd, insec)))
d92aadfd
ILT
1081 bfd_fatal ("set section alignment");
1082
ef5b5368 1083 if (! bfd_set_section_flags (outbfd, outsec, f))
d92aadfd 1084 bfd_fatal ("set section flags");
419093bc
ILT
1085
1086 bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
d92aadfd
ILT
1087}
1088
1089/* Copy the section contents. */
1090
1091static void
1092copy_sections (inbfd, insec, data_ptr)
1093 bfd *inbfd;
1094 asection *insec;
1095 PTR data_ptr;
1096{
1097 bfd *outbfd = (bfd *) data_ptr;
1098 asection *outsec;
1099 bfd_size_type size;
1100 PTR contents;
1101 bfd_size_type reloc_size;
1102
419093bc
ILT
1103 /* FIXME: We don't want to copy the .reginfo section of an ECOFF
1104 file. However, I don't have a good way to describe this section.
1105 We do want to copy the section when using objcopy. */
1106 if (bfd_get_flavour (inbfd) == bfd_target_ecoff_flavour
1107 && strcmp (bfd_section_name (inbfd, insec), ".reginfo") == 0)
1108 return;
1109
90d8edfd 1110 outsec = insec->output_section;
d92aadfd
ILT
1111 assert (outsec != NULL);
1112
1113 size = bfd_get_section_size_before_reloc (insec);
1114 if (size == 0)
1115 return;
1116
1117 /* FIXME: Why are these necessary? */
1118 insec->_cooked_size = insec->_raw_size;
1119 insec->reloc_done = true;
1120
1121 if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
1122 contents = NULL;
1123 else
1124 {
1125 contents = xmalloc (size);
1126 if (! bfd_get_section_contents (inbfd, insec, contents,
1127 (file_ptr) 0, size))
1128 bfd_fatal (bfd_get_filename (inbfd));
1129 }
1130
1131 reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
419093bc 1132 if (reloc_size != 0)
d92aadfd
ILT
1133 {
1134 arelent **relocs;
1135 bfd_size_type reloc_count;
1136
1137 relocs = (arelent **) xmalloc (reloc_size);
1138 reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols);
419093bc 1139 mangle_relocs (outbfd, insec, &relocs, &reloc_count, (char *) contents,
ef5b5368 1140 size);
419093bc
ILT
1141
1142 /* FIXME: refers to internal BFD fields. */
1143 if (outsec->orelocation != (arelent **) NULL)
1144 {
1145 bfd_size_type total_count;
1146 arelent **combined;
1147
1148 total_count = reloc_count + outsec->reloc_count;
1149 combined = (arelent **) xmalloc (total_count * sizeof (arelent));
1150 memcpy (combined, outsec->orelocation,
1151 outsec->reloc_count * sizeof (arelent));
1152 memcpy (combined + outsec->reloc_count, relocs,
1153 (size_t) (reloc_count * sizeof (arelent)));
1154 free (outsec->orelocation);
1155 reloc_count = total_count;
1156 relocs = combined;
1157 }
1158
d92aadfd
ILT
1159 bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
1160 }
1161
1162 if (contents != NULL)
1163 {
1164 if (! bfd_set_section_contents (outbfd, outsec, contents,
90d8edfd 1165 insec->output_offset, size))
d92aadfd
ILT
1166 bfd_fatal (bfd_get_filename (outbfd));
1167 free (contents);
1168 }
1169}
1170
1171/* Some, perhaps all, NetWare targets require changing the relocs used
1172 by the input formats. */
1173
1174static void
419093bc
ILT
1175mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1176 contents_size)
d92aadfd 1177 bfd *outbfd;
ef5b5368 1178 asection *insec;
419093bc 1179 arelent ***relocs_ptr;
ef5b5368 1180 bfd_size_type *reloc_count_ptr;
d92aadfd
ILT
1181 char *contents;
1182 bfd_size_type contents_size;
1183{
1184 switch (bfd_get_arch (outbfd))
1185 {
1186 case bfd_arch_i386:
419093bc
ILT
1187 i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1188 contents, contents_size);
1189 break;
1190 case bfd_arch_alpha:
1191 alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1192 contents, contents_size);
d92aadfd
ILT
1193 break;
1194 default:
419093bc
ILT
1195 default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1196 contents, contents_size);
d92aadfd
ILT
1197 break;
1198 }
1199}
1200
419093bc
ILT
1201/* By default all we need to do for relocs is change the address by
1202 the output_offset. */
1203
1204/*ARGSUSED*/
1205static void
1206default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1207 contents_size)
1208 bfd *outbfd;
1209 asection *insec;
1210 arelent ***relocs_ptr;
1211 bfd_size_type *reloc_count_ptr;
1212 char *contents;
1213 bfd_size_type contents_size;
1214{
1215 if (insec->output_offset != 0)
1216 {
1217 bfd_size_type reloc_count;
1218 register arelent **relocs;
1219 register bfd_size_type i;
1220
1221 reloc_count = *reloc_count_ptr;
1222 relocs = *relocs_ptr;
1223 for (i = 0; i < reloc_count; i++, relocs++)
1224 (*relocs)->address += insec->output_offset;
1225 }
1226}
1227
d92aadfd
ILT
1228/* NetWare on the i386 supports a restricted set of relocs, which are
1229 different from those used on other i386 targets. This routine
1230 converts the relocs. It is, obviously, very target dependent. At
1231 the moment, the nlm32-i386 backend performs similar translations;
1232 however, it is more reliable and efficient to do them here. */
1233
1234static reloc_howto_type nlm_i386_pcrel_howto =
1235 HOWTO (1, /* type */
1236 0, /* rightshift */
1237 2, /* size (0 = byte, 1 = short, 2 = long) */
1238 32, /* bitsize */
1239 true, /* pc_relative */
1240 0, /* bitpos */
1241 complain_overflow_signed, /* complain_on_overflow */
1242 0, /* special_function */
1243 "DISP32", /* name */
1244 true, /* partial_inplace */
1245 0xffffffff, /* src_mask */
1246 0xffffffff, /* dst_mask */
1247 true); /* pcrel_offset */
1248
1249static void
419093bc 1250i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
ef5b5368 1251 contents_size)
d92aadfd 1252 bfd *outbfd;
ef5b5368 1253 asection *insec;
419093bc 1254 arelent ***relocs_ptr;
ef5b5368 1255 bfd_size_type *reloc_count_ptr;
d92aadfd
ILT
1256 char *contents;
1257 bfd_size_type contents_size;
1258{
ef5b5368 1259 bfd_size_type reloc_count, i;
419093bc 1260 arelent **relocs;
ef5b5368
ILT
1261
1262 reloc_count = *reloc_count_ptr;
419093bc 1263 relocs = *relocs_ptr;
ef5b5368 1264 for (i = 0; i < reloc_count; i++)
d92aadfd
ILT
1265 {
1266 arelent *rel;
1267 asymbol *sym;
a30f59a4 1268 bfd_size_type address;
d92aadfd
ILT
1269 bfd_vma addend;
1270
1271 rel = *relocs++;
1272 sym = *rel->sym_ptr_ptr;
1273
a30f59a4
ILT
1274 /* We're moving the relocs from the input section to the output
1275 section, so we must adjust the address accordingly. */
1276 address = rel->address;
1277 rel->address += insec->output_offset;
1278
d92aadfd
ILT
1279 /* Note that no serious harm will ensue if we fail to change a
1280 reloc. The backend will fail when writing out the reloc. */
1281
1282 /* Make sure this reloc is within the data we have. We use only
1283 4 byte relocs here, so we insist on having 4 bytes. */
a30f59a4 1284 if (address + 4 > contents_size)
d92aadfd
ILT
1285 continue;
1286
ef5b5368
ILT
1287 /* A PC relative reloc entirely within a single section is
1288 completely unnecessary. This can be generated by ld -r. */
1289 if (sym == insec->symbol
1290 && rel->howto != NULL
1291 && rel->howto->pc_relative
1292 && ! rel->howto->pcrel_offset)
1293 {
1294 --*reloc_count_ptr;
1295 --relocs;
1296 memmove (relocs, relocs + 1,
419093bc 1297 (size_t) ((reloc_count - i) * sizeof (arelent *)));
ef5b5368
ILT
1298 continue;
1299 }
1300
90d8edfd
ILT
1301 /* Get the amount the relocation will add in. */
1302 addend = rel->addend + sym->value;
1303
1304 /* NetWare doesn't support PC relative relocs against defined
1305 symbols, so we have to eliminate them by doing the relocation
1306 now. We can only do this if the reloc is within a single
1307 section. */
1308 if (rel->howto != NULL
1309 && rel->howto->pc_relative
1310 && bfd_get_section (sym) == insec->output_section)
1311 {
1312 bfd_vma val;
1313
1314 if (rel->howto->pcrel_offset)
a30f59a4 1315 addend -= address;
90d8edfd 1316
a30f59a4 1317 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
90d8edfd 1318 val += addend;
a30f59a4 1319 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
90d8edfd
ILT
1320
1321 --*reloc_count_ptr;
1322 --relocs;
1323 memmove (relocs, relocs + 1,
419093bc 1324 (size_t) ((reloc_count - i) * sizeof (arelent *)));
90d8edfd
ILT
1325 continue;
1326 }
1327
d92aadfd
ILT
1328 /* NetWare doesn't support reloc addends, so we get rid of them
1329 here by simply adding them into the object data. We handle
1330 the symbol value, if any, the same way. */
d92aadfd
ILT
1331 if (addend != 0
1332 && rel->howto != NULL
1333 && rel->howto->rightshift == 0
1334 && rel->howto->size == 2
1335 && rel->howto->bitsize == 32
1336 && rel->howto->bitpos == 0
1337 && rel->howto->src_mask == 0xffffffff
1338 && rel->howto->dst_mask == 0xffffffff)
1339 {
1340 bfd_vma val;
1341
a30f59a4 1342 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
d92aadfd 1343 val += addend;
a30f59a4 1344 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
d92aadfd
ILT
1345
1346 /* Adjust the reloc for the changes we just made. */
1347 rel->addend = 0;
90d8edfd 1348 if (bfd_get_section (sym) != &bfd_und_section)
d92aadfd
ILT
1349 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
1350 }
1351
1352 /* NetWare uses a reloc with pcrel_offset set. We adjust
1353 pc_relative relocs accordingly. We are going to change the
1354 howto field, so we can only do this if the current one is
1355 compatible. We should check that special_function is NULL
1356 here, but at the moment coff-i386 uses a special_function
1357 which does not affect what we are doing here. */
1358 if (rel->howto != NULL
1359 && rel->howto->pc_relative
1360 && ! rel->howto->pcrel_offset
1361 && rel->howto->rightshift == 0
1362 && rel->howto->size == 2
1363 && rel->howto->bitsize == 32
1364 && rel->howto->bitpos == 0
1365 && rel->howto->src_mask == 0xffffffff
1366 && rel->howto->dst_mask == 0xffffffff)
1367 {
1368 bfd_vma val;
1369
1370 /* When pcrel_offset is not set, it means that the negative
1371 of the address of the memory location is stored in the
1372 memory location. We must add it back in. */
a30f59a4
ILT
1373 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1374 val += address;
1375 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
d92aadfd
ILT
1376
1377 /* We must change to a new howto. */
1378 rel->howto = &nlm_i386_pcrel_howto;
1379 }
1380 }
1381}
419093bc
ILT
1382
1383/* On the Alpha the first reloc for every section must be a special
1384 relocs which hold the GP address. Also, the first reloc in the
1385 file must be a special reloc which holds the address of the .lita
1386 section. */
1387
1388static reloc_howto_type nlm32_alpha_nw_howto =
1389 HOWTO (ALPHA_R_NW_RELOC, /* type */
1390 0, /* rightshift */
1391 0, /* size (0 = byte, 1 = short, 2 = long) */
1392 0, /* bitsize */
1393 false, /* pc_relative */
1394 0, /* bitpos */
1395 complain_overflow_dont, /* complain_on_overflow */
1396 0, /* special_function */
1397 "NW_RELOC", /* name */
1398 false, /* partial_inplace */
1399 0, /* src_mask */
1400 0, /* dst_mask */
1401 false); /* pcrel_offset */
1402
1403/*ARGSUSED*/
1404static void
1405alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1406 contents_size)
1407 bfd *outbfd;
1408 asection *insec;
1409 register arelent ***relocs_ptr;
1410 bfd_size_type *reloc_count_ptr;
1411 char *contents;
1412 bfd_size_type contents_size;
1413{
1414 bfd_size_type old_reloc_count;
1415 arelent **old_relocs;
1416 register arelent **relocs;
1417
1418 old_reloc_count = *reloc_count_ptr;
1419 old_relocs = *relocs_ptr;
1420 relocs = (arelent **) xmalloc ((old_reloc_count + 3) * sizeof (arelent *));
1421 *relocs_ptr = relocs;
1422
1423 if (nlm_alpha_backend_data (outbfd)->lita_address == 0)
1424 {
1425 bfd *inbfd;
1426 asection *lita_section;
1427
1428 inbfd = insec->owner;
1429 lita_section = bfd_get_section_by_name (inbfd, _LITA);
1430 if (lita_section != (asection *) NULL)
1431 {
1432 nlm_alpha_backend_data (outbfd)->lita_address =
1433 bfd_get_section_vma (inbfd, lita_section);
1434 nlm_alpha_backend_data (outbfd)->lita_size =
1435 bfd_section_size (inbfd, lita_section);
1436 }
1437 else
1438 {
1439 /* Avoid outputting this reloc again. */
1440 nlm_alpha_backend_data (outbfd)->lita_address = 4;
1441 }
1442
1443 *relocs = (arelent *) xmalloc (sizeof (arelent));
1444 (*relocs)->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
1445 (*relocs)->address = nlm_alpha_backend_data (outbfd)->lita_address;
1446 (*relocs)->addend = nlm_alpha_backend_data (outbfd)->lita_size + 1;
1447 (*relocs)->howto = &nlm32_alpha_nw_howto;
1448 ++relocs;
1449 ++(*reloc_count_ptr);
1450 }
1451
1452 /* Get the GP value from bfd. It is in the .reginfo section. */
1453 if (nlm_alpha_backend_data (outbfd)->gp == 0)
1454 {
1455 bfd *inbfd;
1456 asection *reginfo_sec;
1457 struct ecoff_reginfo sreginfo;
1458
1459 inbfd = insec->owner;
1460 assert (bfd_get_flavour (inbfd) == bfd_target_ecoff_flavour);
1461 reginfo_sec = bfd_get_section_by_name (inbfd, REGINFO);
1462 if (reginfo_sec != (asection *) NULL
1463 && bfd_get_section_contents (inbfd, reginfo_sec,
1464 (PTR) &sreginfo, (file_ptr) 0,
1465 sizeof sreginfo) != false)
1466 nlm_alpha_backend_data (outbfd)->gp = sreginfo.gp_value;
1467 }
1468
1469 *relocs = (arelent *) xmalloc (sizeof (arelent));
1470 (*relocs)->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
1471 (*relocs)->address = nlm_alpha_backend_data (outbfd)->gp;
1472 (*relocs)->addend = 0;
1473 (*relocs)->howto = &nlm32_alpha_nw_howto;
1474 ++relocs;
1475 ++(*reloc_count_ptr);
1476
1477 memcpy ((PTR) relocs, (PTR) old_relocs,
1478 (size_t) old_reloc_count * sizeof (arelent *));
1479 relocs[old_reloc_count] = (arelent *) NULL;
1480
1481 free (old_relocs);
1482
1483 if (insec->output_offset != 0)
1484 {
1485 register bfd_size_type i;
1486
1487 for (i = 0; i < old_reloc_count; i++, relocs++)
1488 (*relocs)->address += insec->output_offset;
1489 }
1490}
0f6df2ee
ILT
1491\f
1492/* Name of linker. */
1493#ifndef LD_NAME
1494#define LD_NAME "ld"
1495#endif
1496
1497/* Temporary file name base. */
1498static char *temp_filename;
1499
1500/* The user has specified several input files. Invoke the linker to
1501 link them all together, and convert and delete the resulting output
1502 file. */
1503
1504static char *
1505link_inputs (inputs, ld)
1506 struct string_list *inputs;
1507 char *ld;
1508{
1509 size_t c;
1510 struct string_list *q;
1511 char **argv;
1512 size_t i;
1513 int pid;
1514 int status;
1515
1516 c = 0;
1517 for (q = inputs; q != NULL; q = q->next)
1518 ++c;
1519
1520 argv = (char **) alloca (c + 5);
1521
1522#ifndef __MSDOS__
1523 if (ld == NULL)
1524 {
1525 char *p;
1526
1527 /* Find the linker to invoke based on how nlmconv was run. */
1528 p = program_name + strlen (program_name);
1529 while (p != program_name)
1530 {
1531 if (p[-1] == '/')
1532 {
1533 ld = (char *) xmalloc (p - program_name + strlen (LD_NAME) + 1);
1534 memcpy (ld, program_name, p - program_name);
1535 strcpy (ld + (p - program_name), LD_NAME);
1536 break;
1537 }
1538 --p;
1539 }
1540 }
1541#endif
1542
1543 if (ld == NULL)
1544 ld = (char *) LD_NAME;
1545
1546 choose_temp_base ();
1547
1548 unlink_on_exit = xmalloc (strlen (temp_filename) + 3);
1549 sprintf (unlink_on_exit, "%s.O", temp_filename);
1550
1551 argv[0] = ld;
1552 argv[1] = (char *) "-r";
1553 argv[2] = (char *) "-o";
1554 argv[3] = unlink_on_exit;
1555 i = 4;
1556 for (q = inputs; q != NULL; q = q->next, i++)
1557 argv[i] = q->string;
1558 argv[i] = NULL;
1559
1560 if (debug)
1561 {
1562 for (i = 0; argv[i] != NULL; i++)
1563 fprintf (stderr, " %s", argv[i]);
1564 fprintf (stderr, "\n");
1565 }
1566
1567 pid = pexecute (ld, argv);
1568
1569 if (waitpid (pid, &status, 0) < 0)
1570 {
1571 perror ("waitpid");
1572 unlink (unlink_on_exit);
1573 exit (1);
1574 }
1575
1576 if (status != 0)
1577 {
1578 fprintf (stderr, "%s: Execution of %s failed\n", program_name, ld);
1579 unlink (unlink_on_exit);
1580 exit (1);
1581 }
1582
1583 return unlink_on_exit;
1584}
1585
1586/* Choose a temporary file name. Stolen from gcc.c. */
1587
1588static const char *
1589choose_temp_base_try (try, base)
1590 const char *try;
1591 const char *base;
1592{
1593 const char *rv;
1594
1595 if (base)
1596 rv = base;
1597 else if (try == NULL)
1598 rv = NULL;
1599 else if (access (try, R_OK | W_OK) != 0)
1600 rv = NULL;
1601 else
1602 rv = try;
1603 return rv;
1604}
1605
1606static void
1607choose_temp_base ()
1608{
1609 const char *base = NULL;
1610 int len;
1611
1612 base = choose_temp_base_try (getenv ("TMPDIR"), base);
1613 base = choose_temp_base_try (getenv ("TMP"), base);
1614 base = choose_temp_base_try (getenv ("TEMP"), base);
1615
1616#ifdef P_tmpdir
1617 base = choose_temp_base_try (P_tmpdir, base);
1618#endif
1619
1620 base = choose_temp_base_try ("/usr/tmp", base);
1621 base = choose_temp_base_try ("/tmp", base);
1622
1623 /* If all else fails, use the current directory! */
1624 if (base == NULL)
1625 base = "./";
1626
1627 len = strlen (base);
1628 temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1);
1629 strcpy (temp_filename, base);
1630 if (len > 0 && temp_filename[len-1] != '/')
1631 temp_filename[len++] = '/';
1632 strcpy (temp_filename + len, "ccXXXXXX");
1633
1634 mktemp (temp_filename);
1635 if (*temp_filename == '\0')
1636 abort ();
1637}
1638
1639/* Execute a job. Stolen from gcc.c. */
1640
1641#ifndef OS2
1642#ifdef __MSDOS__
1643
1644static int
1645pexecute (program, argv)
1646 char *program;
1647 char *argv[];
1648{
1649 char *scmd, *rf;
1650 FILE *argfile;
1651 int i;
1652
1653 scmd = (char *)malloc (strlen (program) + strlen (temp_filename) + 10);
1654 rf = scmd + strlen(program) + 2 + el;
1655 sprintf (scmd, "%s.exe @%s.gp", program, temp_filename);
1656 argfile = fopen (rf, "w");
1657 if (argfile == 0)
1658 pfatal_with_name (rf);
1659
1660 for (i=1; argv[i]; i++)
1661 {
1662 char *cp;
1663 for (cp = argv[i]; *cp; cp++)
1664 {
1665 if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
1666 fputc ('\\', argfile);
1667 fputc (*cp, argfile);
1668 }
1669 fputc ('\n', argfile);
1670 }
1671 fclose (argfile);
1672
1673 i = system (scmd);
1674
1675 remove (rf);
1676
1677 if (i == -1)
1678 {
1679 perror (program);
1680 return MIN_FATAL_STATUS << 8;
1681 }
1682
1683 return i << 8;
1684}
1685
1686#else /* not __MSDOS__ */
1687
1688static int
1689pexecute (program, argv)
1690 char *program;
1691 char *argv[];
1692{
1693 int pid;
1694 int retries, sleep_interval;
1695
1696 /* Fork a subprocess; wait and retry if it fails. */
1697 sleep_interval = 1;
1698 for (retries = 0; retries < 4; retries++)
1699 {
1700 pid = vfork ();
1701 if (pid >= 0)
1702 break;
1703 sleep (sleep_interval);
1704 sleep_interval *= 2;
1705 }
1706
1707 switch (pid)
1708 {
1709 case -1:
1710#ifdef vfork
1711 perror ("fork");
1712#else
1713 perror ("vfork");
1714#endif
1715 exit (1);
1716 /* NOTREACHED */
1717 return 0;
1718
1719 case 0: /* child */
1720 /* Exec the program. */
1721 execvp (program, argv);
1722 perror (program);
1723 exit (1);
1724 /* NOTREACHED */
1725 return 0;
1726
1727 default:
1728 /* Return child's process number. */
1729 return pid;
1730 }
1731}
1732
1733#endif /* not __MSDOS__ */
1734#else /* not OS2 */
1735
1736static int
1737pexecute (program, argv)
1738 char *program;
1739 char *argv[];
1740{
1741 return spawnvp (1, program, argv);
1742}
1743#endif /* not OS2 */
This page took 0.10299 seconds and 4 git commands to generate.