OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [binutils/] [nlmconv.c] - Blame information for rev 249

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
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 = &copyright_hdr_struct;
286
  memset ((void *) &copyright_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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.