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