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 98

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

powered by: WebSVN 2.1.0

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