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