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