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