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