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