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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [binutils/] [nlmconv.c] - Blame information for rev 38

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

Line No. Rev Author Line
1 38 julius
/* nlmconv.c -- NLM conversion program
2
   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3
   2003, 2004, 2005, 2006, 2007 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 "safe-ctype.h"
41
 
42
#include "ansidecl.h"
43
#include <time.h>
44
#include <sys/stat.h>
45
#include <sys/file.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 (strcmp (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 (outbfd, NLM_UNINITIALIZED_DATA_NAME);
399
      if (bss_sec == NULL
400
          || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC)
401
          || ! bfd_set_section_alignment (outbfd, bss_sec, 1))
402
        bfd_fatal (_("make .bss section"));
403
    }
404
 
405
  /* We store the original section names in the .nlmsections section,
406
     so that programs which understand it can resurrect the original
407
     sections from the NLM.  We will put a pointer to .nlmsections in
408
     the NLM header area.  */
409
  secsec = bfd_make_section (outbfd, ".nlmsections");
410
  if (secsec == NULL)
411
    bfd_fatal (_("make .nlmsections section"));
412
  if (! bfd_set_section_flags (outbfd, secsec, SEC_HAS_CONTENTS))
413
    bfd_fatal (_("set .nlmsections flags"));
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;
480
 
481
                      new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1);
482
                      new[0] = outlead;
483
                      strcpy (new + 1, bfd_asymbol_name (sym) + 1);
484
                      sym->name = new;
485
                    }
486
                }
487
            }
488
          else
489
            {
490
              char *new;
491
 
492
              new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2);
493
              new[0] = outlead;
494
              strcpy (new + 1, bfd_asymbol_name (sym));
495
              sym->name = new;
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 (outbfd, ".nlmcustom");
718
          if (custom_section == NULL
719
              || ! bfd_set_section_size (outbfd, custom_section, custom_size)
720
              || ! bfd_set_section_flags (outbfd, custom_section,
721
                                          SEC_HAS_CONTENTS))
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 (outbfd, ".nlmhelp");
739
          if (help_section == NULL
740
              || ! bfd_set_section_size (outbfd, help_section, help_size)
741
              || ! bfd_set_section_flags (outbfd, help_section,
742
                                          SEC_HAS_CONTENTS))
743
            bfd_fatal (_("help section"));
744
          LITMEMCPY (nlm_extended_header (outbfd)->stamp, "MeSsAgEs");
745
        }
746
    }
747
  if (message_file != NULL)
748
    {
749
      message_data = fopen (message_file, "r");
750
      if (message_data == NULL
751
          || fstat (fileno (message_data), &st) < 0)
752
        {
753
          fprintf (stderr, "%s:%s: %s\n", program_name, message_file,
754
                   strerror (errno));
755
          message_file = NULL;
756
        }
757
      else
758
        {
759
          message_size = st.st_size;
760
          message_section = bfd_make_section (outbfd, ".nlmmessages");
761
          if (message_section == NULL
762
              || ! bfd_set_section_size (outbfd, message_section, message_size)
763
              || ! bfd_set_section_flags (outbfd, message_section,
764
                                          SEC_HAS_CONTENTS))
765
            bfd_fatal (_("message section"));
766
          LITMEMCPY (nlm_extended_header (outbfd)->stamp, "MeSsAgEs");
767
        }
768
    }
769
  if (modules != NULL)
770
    {
771
      struct string_list *l;
772
 
773
      module_size = 0;
774
      for (l = modules; l != NULL; l = l->next)
775
        module_size += strlen (l->string) + 1;
776
      module_section = bfd_make_section (outbfd, ".nlmmodules");
777
      if (module_section == NULL
778
          || ! bfd_set_section_size (outbfd, module_section, module_size)
779
          || ! bfd_set_section_flags (outbfd, module_section,
780
                                      SEC_HAS_CONTENTS))
781
        bfd_fatal (_("module section"));
782
    }
783
  if (rpc_file != NULL)
784
    {
785
      rpc_data = fopen (rpc_file, "r");
786
      if (rpc_data == NULL
787
          || fstat (fileno (rpc_data), &st) < 0)
788
        {
789
          fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file,
790
                   strerror (errno));
791
          rpc_file = NULL;
792
        }
793
      else
794
        {
795
          rpc_size = st.st_size;
796
          rpc_section = bfd_make_section (outbfd, ".nlmrpc");
797
          if (rpc_section == NULL
798
              || ! bfd_set_section_size (outbfd, rpc_section, rpc_size)
799
              || ! bfd_set_section_flags (outbfd, rpc_section,
800
                                          SEC_HAS_CONTENTS))
801
            bfd_fatal (_("rpc section"));
802
          LITMEMCPY (nlm_extended_header (outbfd)->stamp, "MeSsAgEs");
803
        }
804
    }
805
  if (sharelib_file != NULL)
806
    {
807
      sharedbfd = bfd_openr (sharelib_file, output_format);
808
      if (sharedbfd == NULL
809
          || ! bfd_check_format (sharedbfd, bfd_object))
810
        {
811
          fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
812
                   bfd_errmsg (bfd_get_error ()));
813
          sharelib_file = NULL;
814
        }
815
      else
816
        {
817
          sharedhdr = *nlm_fixed_header (sharedbfd);
818
          bfd_close (sharedbfd);
819
          shared_data = fopen (sharelib_file, "r");
820
          if (shared_data == NULL
821
              || (fstat (fileno (shared_data), &st) < 0))
822
            {
823
              fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
824
                       strerror (errno));
825
              sharelib_file = NULL;
826
            }
827
          else
828
            {
829
              /* If we were clever, we could just copy out the
830
                 sections of the shared library which we actually
831
                 need.  However, we would have to figure out the sizes
832
                 of the external and public information, and that can
833
                 not be done without reading through them.  */
834
              if (sharedhdr.uninitializedDataSize > 0)
835
                {
836
                  /* There is no place to record this information.  */
837
                  non_fatal (_("%s: warning: shared libraries can not have uninitialized data"),
838
                             sharelib_file);
839
                }
840
              shared_offset = st.st_size;
841
              if (shared_offset > (size_t) sharedhdr.codeImageOffset)
842
                shared_offset = sharedhdr.codeImageOffset;
843
              if (shared_offset > (size_t) sharedhdr.dataImageOffset)
844
                shared_offset = sharedhdr.dataImageOffset;
845
              if (shared_offset > (size_t) sharedhdr.relocationFixupOffset)
846
                shared_offset = sharedhdr.relocationFixupOffset;
847
              if (shared_offset > (size_t) sharedhdr.externalReferencesOffset)
848
                shared_offset = sharedhdr.externalReferencesOffset;
849
              if (shared_offset > (size_t) sharedhdr.publicsOffset)
850
                shared_offset = sharedhdr.publicsOffset;
851
              shared_size = st.st_size - shared_offset;
852
              shared_section = bfd_make_section (outbfd, ".nlmshared");
853
              if (shared_section == NULL
854
                  || ! bfd_set_section_size (outbfd, shared_section,
855
                                             shared_size)
856
                  || ! bfd_set_section_flags (outbfd, shared_section,
857
                                              SEC_HAS_CONTENTS))
858
                bfd_fatal (_("shared section"));
859
              LITMEMCPY (nlm_extended_header (outbfd)->stamp, "MeSsAgEs");
860
            }
861
        }
862
    }
863
 
864
  /* Check whether a version was given.  */
865
  if (!CONST_STRNEQ (version_hdr->stamp, "VeRsIoN#"))
866
    non_fatal (_("warning: No version number given"));
867
 
868
  /* At least for now, always create an extended header, because that
869
     is what NLMLINK does.  */
870
  LITMEMCPY (nlm_extended_header (outbfd)->stamp, "MeSsAgEs");
871
 
872
  LITMEMCPY (nlm_cygnus_ext_header (outbfd)->stamp, "CyGnUsEx");
873
 
874
  /* If the date was not given, force it in.  */
875
  if (nlm_version_header (outbfd)->month == 0
876
      && nlm_version_header (outbfd)->day == 0
877
      && nlm_version_header (outbfd)->year == 0)
878
    {
879
      time_t now;
880
      struct tm *ptm;
881
 
882
      time (&now);
883
      ptm = localtime (&now);
884
      nlm_version_header (outbfd)->month = ptm->tm_mon + 1;
885
      nlm_version_header (outbfd)->day = ptm->tm_mday;
886
      nlm_version_header (outbfd)->year = ptm->tm_year + 1900;
887
      LITMEMCPY (version_hdr->stamp, "VeRsIoN#");
888
    }
889
 
890
#ifdef NLMCONV_POWERPC
891
  /* Resolve the stubs we build for PowerPC NetWare.  */
892
  if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
893
    powerpc_resolve_stubs (inbfd, outbfd);
894
#endif
895
 
896
  /* Copy over the sections.  */
897
  bfd_map_over_sections (inbfd, copy_sections, (void *) outbfd);
898
 
899
  /* Finish up the header information.  */
900
  if (custom_file != NULL)
901
    {
902
      void *data;
903
 
904
      data = xmalloc (custom_size);
905
      if (fread (data, 1, custom_size, custom_data) != custom_size)
906
        non_fatal (_("%s: read: %s"), custom_file, strerror (errno));
907
      else
908
        {
909
          if (! bfd_set_section_contents (outbfd, custom_section, data,
910
                                          (file_ptr) 0, custom_size))
911
            bfd_fatal (_("custom section"));
912
          nlm_fixed_header (outbfd)->customDataOffset =
913
            custom_section->filepos;
914
          nlm_fixed_header (outbfd)->customDataSize = custom_size;
915
        }
916
      free (data);
917
    }
918
  if (! debug_info)
919
    {
920
      /* As a special hack, the backend recognizes a debugInfoOffset
921
         of -1 to mean that it should not output any debugging
922
         information.  This can not be handling by fiddling with the
923
         symbol table because exported symbols appear in both the
924
         export information and the debugging information.  */
925
      nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1;
926
    }
927
  if (full_map)
928
    non_fatal (_("warning: FULLMAP is not supported; try ld -M"));
929
  if (help_file != NULL)
930
    {
931
      void *data;
932
 
933
      data = xmalloc (help_size);
934
      if (fread (data, 1, help_size, help_data) != help_size)
935
        non_fatal (_("%s: read: %s"), help_file, strerror (errno));
936
      else
937
        {
938
          if (! bfd_set_section_contents (outbfd, help_section, data,
939
                                          (file_ptr) 0, help_size))
940
            bfd_fatal (_("help section"));
941
          nlm_extended_header (outbfd)->helpFileOffset =
942
            help_section->filepos;
943
          nlm_extended_header (outbfd)->helpFileLength = help_size;
944
        }
945
      free (data);
946
    }
947
  if (message_file != NULL)
948
    {
949
      void *data;
950
 
951
      data = xmalloc (message_size);
952
      if (fread (data, 1, message_size, message_data) != message_size)
953
        non_fatal (_("%s: read: %s"), message_file, strerror (errno));
954
      else
955
        {
956
          if (! bfd_set_section_contents (outbfd, message_section, data,
957
                                          (file_ptr) 0, message_size))
958
            bfd_fatal (_("message section"));
959
          nlm_extended_header (outbfd)->messageFileOffset =
960
            message_section->filepos;
961
          nlm_extended_header (outbfd)->messageFileLength = message_size;
962
 
963
          /* FIXME: Are these offsets correct on all platforms?  Are
964
             they 32 bits on all platforms?  What endianness?  */
965
          nlm_extended_header (outbfd)->languageID =
966
            bfd_h_get_32 (outbfd, (bfd_byte *) data + 106);
967
          nlm_extended_header (outbfd)->messageCount =
968
            bfd_h_get_32 (outbfd, (bfd_byte *) data + 110);
969
        }
970
      free (data);
971
    }
972
  if (modules != NULL)
973
    {
974
      void *data;
975
      unsigned char *set;
976
      struct string_list *l;
977
      bfd_size_type c;
978
 
979
      data = xmalloc (module_size);
980
      c = 0;
981
      set = (unsigned char *) data;
982
      for (l = modules; l != NULL; l = l->next)
983
        {
984
          *set = strlen (l->string);
985
          strncpy ((char *) set + 1, l->string, *set);
986
          set += *set + 1;
987
          ++c;
988
        }
989
      if (! bfd_set_section_contents (outbfd, module_section, data,
990
                                      (file_ptr) 0, module_size))
991
        bfd_fatal (_("module section"));
992
      nlm_fixed_header (outbfd)->moduleDependencyOffset =
993
        module_section->filepos;
994
      nlm_fixed_header (outbfd)->numberOfModuleDependencies = c;
995
    }
996
  if (rpc_file != NULL)
997
    {
998
      void *data;
999
 
1000
      data = xmalloc (rpc_size);
1001
      if (fread (data, 1, rpc_size, rpc_data) != rpc_size)
1002
        non_fatal (_("%s: read: %s"), rpc_file, strerror (errno));
1003
      else
1004
        {
1005
          if (! bfd_set_section_contents (outbfd, rpc_section, data,
1006
                                          (file_ptr) 0, rpc_size))
1007
            bfd_fatal (_("rpc section"));
1008
          nlm_extended_header (outbfd)->RPCDataOffset =
1009
            rpc_section->filepos;
1010
          nlm_extended_header (outbfd)->RPCDataLength = rpc_size;
1011
        }
1012
      free (data);
1013
    }
1014
  if (sharelib_file != NULL)
1015
    {
1016
      void *data;
1017
 
1018
      data = xmalloc (shared_size);
1019
      if (fseek (shared_data, shared_offset, SEEK_SET) != 0
1020
          || fread (data, 1, shared_size, shared_data) != shared_size)
1021
        non_fatal (_("%s: read: %s"), sharelib_file, strerror (errno));
1022
      else
1023
        {
1024
          if (! bfd_set_section_contents (outbfd, shared_section, data,
1025
                                          (file_ptr) 0, shared_size))
1026
            bfd_fatal (_("shared section"));
1027
        }
1028
      nlm_extended_header (outbfd)->sharedCodeOffset =
1029
        sharedhdr.codeImageOffset - shared_offset + shared_section->filepos;
1030
      nlm_extended_header (outbfd)->sharedCodeLength =
1031
        sharedhdr.codeImageSize;
1032
      nlm_extended_header (outbfd)->sharedDataOffset =
1033
        sharedhdr.dataImageOffset - shared_offset + shared_section->filepos;
1034
      nlm_extended_header (outbfd)->sharedDataLength =
1035
        sharedhdr.dataImageSize;
1036
      nlm_extended_header (outbfd)->sharedRelocationFixupOffset =
1037
        (sharedhdr.relocationFixupOffset
1038
         - shared_offset
1039
         + shared_section->filepos);
1040
      nlm_extended_header (outbfd)->sharedRelocationFixupCount =
1041
        sharedhdr.numberOfRelocationFixups;
1042
      nlm_extended_header (outbfd)->sharedExternalReferenceOffset =
1043
        (sharedhdr.externalReferencesOffset
1044
         - shared_offset
1045
         + shared_section->filepos);
1046
      nlm_extended_header (outbfd)->sharedExternalReferenceCount =
1047
        sharedhdr.numberOfExternalReferences;
1048
      nlm_extended_header (outbfd)->sharedPublicsOffset =
1049
        sharedhdr.publicsOffset - shared_offset + shared_section->filepos;
1050
      nlm_extended_header (outbfd)->sharedPublicsCount =
1051
        sharedhdr.numberOfPublics;
1052
      nlm_extended_header (outbfd)->sharedDebugRecordOffset =
1053
        sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos;
1054
      nlm_extended_header (outbfd)->sharedDebugRecordCount =
1055
        sharedhdr.numberOfDebugRecords;
1056
      nlm_extended_header (outbfd)->SharedInitializationOffset =
1057
        sharedhdr.codeStartOffset;
1058
      nlm_extended_header (outbfd)->SharedExitProcedureOffset =
1059
        sharedhdr.exitProcedureOffset;
1060
      free (data);
1061
    }
1062
 
1063
  {
1064
    const int    max_len  = NLM_MODULE_NAME_SIZE - 2;
1065
    const char * filename = lbasename (output_file);
1066
 
1067
    len = strlen (filename);
1068
    if (len > max_len)
1069
      len = max_len;
1070
    nlm_fixed_header (outbfd)->moduleName[0] = len;
1071
 
1072
    strncpy (nlm_fixed_header (outbfd)->moduleName + 1, filename, max_len);
1073
    nlm_fixed_header (outbfd)->moduleName[max_len + 1] = '\0';
1074
 
1075
    for (modname = nlm_fixed_header (outbfd)->moduleName;
1076
         *modname != '\0';
1077
         modname++)
1078
      *modname = TOUPPER (*modname);
1079
  }
1080
 
1081
  strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
1082
           NLM_OLD_THREAD_NAME_LENGTH);
1083
 
1084
  nlm_cygnus_ext_header (outbfd)->offset = secsec->filepos;
1085
  nlm_cygnus_ext_header (outbfd)->length = bfd_section_size (outbfd, secsec);
1086
 
1087
  if (! bfd_close (outbfd))
1088
    bfd_fatal (output_file);
1089
  if (! bfd_close (inbfd))
1090
    bfd_fatal (input_file);
1091
 
1092
  if (unlink_on_exit != NULL)
1093
    unlink (unlink_on_exit);
1094
 
1095
  return 0;
1096
}
1097
 
1098
 
1099
/* Show a usage message and exit.  */
1100
 
1101
static void
1102
show_usage (FILE *file, int status)
1103
{
1104
  fprintf (file, _("Usage: %s [option(s)] [in-file [out-file]]\n"), program_name);
1105
  fprintf (file, _(" Convert an object file into a NetWare Loadable Module\n"));
1106
  fprintf (file, _(" The options are:\n\
1107
  -I --input-target=<bfdname>   Set the input binary file format\n\
1108
  -O --output-target=<bfdname>  Set the output binary file format\n\
1109
  -T --header-file=<file>       Read <file> for NLM header information\n\
1110
  -l --linker=<linker>          Use <linker> for any linking\n\
1111
  -d --debug                    Display on stderr the linker command line\n\
1112
  @<file>                       Read options from <file>.\n\
1113
  -h --help                     Display this information\n\
1114
  -v --version                  Display the program's version\n\
1115
"));
1116
  if (REPORT_BUGS_TO[0] && status == 0)
1117
    fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
1118
  exit (status);
1119
}
1120
 
1121
/* Select the output format based on the input architecture, machine,
1122
   and endianness.  This chooses the appropriate NLM target.  */
1123
 
1124
static const char *
1125
select_output_format (enum bfd_architecture arch, unsigned long mach,
1126
                      bfd_boolean bigendian ATTRIBUTE_UNUSED)
1127
{
1128
  switch (arch)
1129
    {
1130
#ifdef NLMCONV_I386
1131
    case bfd_arch_i386:
1132
      return "nlm32-i386";
1133
#endif
1134
#ifdef NLMCONV_SPARC
1135
    case bfd_arch_sparc:
1136
      return "nlm32-sparc";
1137
#endif
1138
#ifdef NLMCONV_ALPHA
1139
    case bfd_arch_alpha:
1140
      return "nlm32-alpha";
1141
#endif
1142
#ifdef NLMCONV_POWERPC
1143
    case bfd_arch_powerpc:
1144
      return "nlm32-powerpc";
1145
#endif
1146
    default:
1147
      fatal (_("support not compiled in for %s"),
1148
             bfd_printable_arch_mach (arch, mach));
1149
    }
1150
  /*NOTREACHED*/
1151
}
1152
 
1153
/* The BFD sections are copied in two passes.  This function selects
1154
   the output section for each input section, and sets up the section
1155
   name, size, etc.  */
1156
 
1157
static void
1158
setup_sections (bfd *inbfd ATTRIBUTE_UNUSED, asection *insec, void *data_ptr)
1159
{
1160
  bfd *outbfd = (bfd *) data_ptr;
1161
  flagword f;
1162
  const char *outname;
1163
  asection *outsec;
1164
  bfd_vma offset;
1165
  bfd_size_type align;
1166
  bfd_size_type add;
1167
  bfd_size_type secsecsize;
1168
 
1169
  f = bfd_get_section_flags (inbfd, insec);
1170
  if (f & SEC_CODE)
1171
    outname = NLM_CODE_NAME;
1172
  else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS))
1173
    outname = NLM_INITIALIZED_DATA_NAME;
1174
  else if (f & SEC_ALLOC)
1175
    outname = NLM_UNINITIALIZED_DATA_NAME;
1176
  else
1177
    outname = bfd_section_name (inbfd, insec);
1178
 
1179
  outsec = bfd_get_section_by_name (outbfd, outname);
1180
  if (outsec == NULL)
1181
    {
1182
      outsec = bfd_make_section (outbfd, outname);
1183
      if (outsec == NULL)
1184
        bfd_fatal (_("make section"));
1185
    }
1186
 
1187
  insec->output_section = outsec;
1188
 
1189
  offset = bfd_section_size (outbfd, outsec);
1190
  align = 1 << bfd_section_alignment (inbfd, insec);
1191
  add = ((offset + align - 1) &~ (align - 1)) - offset;
1192
  insec->output_offset = offset + add;
1193
 
1194
  if (! bfd_set_section_size (outbfd, outsec,
1195
                              (bfd_section_size (outbfd, outsec)
1196
                               + bfd_section_size (inbfd, insec)
1197
                               + add)))
1198
    bfd_fatal (_("set section size"));
1199
 
1200
  if ((bfd_section_alignment (inbfd, insec)
1201
       > bfd_section_alignment (outbfd, outsec))
1202
      && ! bfd_set_section_alignment (outbfd, outsec,
1203
                                      bfd_section_alignment (inbfd, insec)))
1204
    bfd_fatal (_("set section alignment"));
1205
 
1206
  if (! bfd_set_section_flags (outbfd, outsec,
1207
                               f | bfd_get_section_flags (outbfd, outsec)))
1208
    bfd_fatal (_("set section flags"));
1209
 
1210
  bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
1211
 
1212
  /* For each input section we allocate space for an entry in
1213
     .nlmsections.  */
1214
  secsecsize = bfd_section_size (outbfd, secsec);
1215
  secsecsize += strlen (bfd_section_name (inbfd, insec)) + 1;
1216
  secsecsize = (secsecsize + 3) &~ 3;
1217
  secsecsize += 8;
1218
  if (! bfd_set_section_size (outbfd, secsec, secsecsize))
1219
    bfd_fatal (_("set .nlmsections size"));
1220
}
1221
 
1222
/* Copy the section contents.  */
1223
 
1224
static void
1225
copy_sections (bfd *inbfd, asection *insec, void *data_ptr)
1226
{
1227
  static bfd_size_type secsecoff = 0;
1228
  bfd *outbfd = (bfd *) data_ptr;
1229
  const char *inname;
1230
  asection *outsec;
1231
  bfd_size_type size;
1232
  void *contents;
1233
  long reloc_size;
1234
  bfd_byte buf[4];
1235
  bfd_size_type add;
1236
 
1237
  inname = bfd_section_name (inbfd, insec);
1238
 
1239
  outsec = insec->output_section;
1240
  assert (outsec != NULL);
1241
 
1242
  size = bfd_get_section_size (insec);
1243
 
1244
  if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
1245
    contents = NULL;
1246
  else
1247
    {
1248
      contents = xmalloc (size);
1249
      if (! bfd_get_section_contents (inbfd, insec, contents,
1250
                                      (file_ptr) 0, size))
1251
        bfd_fatal (bfd_get_filename (inbfd));
1252
    }
1253
 
1254
  reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
1255
  if (reloc_size < 0)
1256
    bfd_fatal (bfd_get_filename (inbfd));
1257
  if (reloc_size != 0)
1258
    {
1259
      arelent **relocs;
1260
      long reloc_count;
1261
 
1262
      relocs = (arelent **) xmalloc (reloc_size);
1263
      reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols);
1264
      if (reloc_count < 0)
1265
        bfd_fatal (bfd_get_filename (inbfd));
1266
      mangle_relocs (outbfd, insec, &relocs, &reloc_count, (char *) contents,
1267
                     size);
1268
 
1269
      /* FIXME: refers to internal BFD fields.  */
1270
      if (outsec->orelocation != (arelent **) NULL)
1271
        {
1272
          bfd_size_type total_count;
1273
          arelent **combined;
1274
 
1275
          total_count = reloc_count + outsec->reloc_count;
1276
          combined = (arelent **) xmalloc (total_count * sizeof (arelent *));
1277
          memcpy (combined, outsec->orelocation,
1278
                  outsec->reloc_count * sizeof (arelent *));
1279
          memcpy (combined + outsec->reloc_count, relocs,
1280
                  (size_t) (reloc_count * sizeof (arelent *)));
1281
          free (outsec->orelocation);
1282
          reloc_count = total_count;
1283
          relocs = combined;
1284
        }
1285
 
1286
      bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
1287
    }
1288
 
1289
  if (contents != NULL)
1290
    {
1291
      if (! bfd_set_section_contents (outbfd, outsec, contents,
1292
                                      insec->output_offset, size))
1293
        bfd_fatal (bfd_get_filename (outbfd));
1294
      free (contents);
1295
    }
1296
 
1297
  /* Add this section to .nlmsections.  */
1298
  if (! bfd_set_section_contents (outbfd, secsec, (void *) inname, secsecoff,
1299
                                  strlen (inname) + 1))
1300
    bfd_fatal (_("set .nlmsection contents"));
1301
  secsecoff += strlen (inname) + 1;
1302
 
1303
  add = ((secsecoff + 3) &~ 3) - secsecoff;
1304
  if (add != 0)
1305
    {
1306
      bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
1307
      if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, add))
1308
        bfd_fatal (_("set .nlmsection contents"));
1309
      secsecoff += add;
1310
    }
1311
 
1312
  if (contents != NULL)
1313
    bfd_h_put_32 (outbfd, (bfd_vma) outsec->filepos, buf);
1314
  else
1315
    bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
1316
  if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
1317
    bfd_fatal (_("set .nlmsection contents"));
1318
  secsecoff += 4;
1319
 
1320
  bfd_h_put_32 (outbfd, (bfd_vma) size, buf);
1321
  if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
1322
    bfd_fatal (_("set .nlmsection contents"));
1323
  secsecoff += 4;
1324
}
1325
 
1326
/* Some, perhaps all, NetWare targets require changing the relocs used
1327
   by the input formats.  */
1328
 
1329
static void
1330
mangle_relocs (bfd *outbfd, asection *insec, arelent ***relocs_ptr,
1331
               long *reloc_count_ptr, char *contents,
1332
               bfd_size_type contents_size)
1333
{
1334
  switch (bfd_get_arch (outbfd))
1335
    {
1336
#ifdef NLMCONV_I386
1337
    case bfd_arch_i386:
1338
      i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1339
                          contents, contents_size);
1340
      break;
1341
#endif
1342
#ifdef NLMCONV_ALPHA
1343
    case bfd_arch_alpha:
1344
      alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1345
                           contents, contents_size);
1346
      break;
1347
#endif
1348
#ifdef NLMCONV_POWERPC
1349
    case bfd_arch_powerpc:
1350
      powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1351
                             contents, contents_size);
1352
      break;
1353
#endif
1354
    default:
1355
      default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1356
                             contents, contents_size);
1357
      break;
1358
    }
1359
}
1360
 
1361
/* By default all we need to do for relocs is change the address by
1362
   the output_offset.  */
1363
 
1364
static void
1365
default_mangle_relocs (bfd *outbfd ATTRIBUTE_UNUSED, asection *insec,
1366
                       arelent ***relocs_ptr, long *reloc_count_ptr,
1367
                       char *contents ATTRIBUTE_UNUSED,
1368
                       bfd_size_type contents_size ATTRIBUTE_UNUSED)
1369
{
1370
  if (insec->output_offset != 0)
1371
    {
1372
      long reloc_count;
1373
      arelent **relocs;
1374
      long i;
1375
 
1376
      reloc_count = *reloc_count_ptr;
1377
      relocs = *relocs_ptr;
1378
      for (i = 0; i < reloc_count; i++, relocs++)
1379
        (*relocs)->address += insec->output_offset;
1380
    }
1381
}
1382
 
1383
#ifdef NLMCONV_I386
1384
 
1385
/* NetWare on the i386 supports a restricted set of relocs, which are
1386
   different from those used on other i386 targets.  This routine
1387
   converts the relocs.  It is, obviously, very target dependent.  At
1388
   the moment, the nlm32-i386 backend performs similar translations;
1389
   however, it is more reliable and efficient to do them here.  */
1390
 
1391
static reloc_howto_type nlm_i386_pcrel_howto =
1392
  HOWTO (1,                     /* type */
1393
         0,                      /* rightshift */
1394
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
1395
         32,                    /* bitsize */
1396
         TRUE,                  /* pc_relative */
1397
         0,                      /* bitpos */
1398
         complain_overflow_signed, /* complain_on_overflow */
1399
         0,                      /* special_function */
1400
         "DISP32",              /* name */
1401
         TRUE,                  /* partial_inplace */
1402
         0xffffffff,            /* src_mask */
1403
         0xffffffff,            /* dst_mask */
1404
         TRUE);                 /* pcrel_offset */
1405
 
1406
static void
1407
i386_mangle_relocs (bfd *outbfd, asection *insec, arelent ***relocs_ptr,
1408
                    long *reloc_count_ptr, char *contents,
1409
                    bfd_size_type contents_size)
1410
{
1411
  long reloc_count, i;
1412
  arelent **relocs;
1413
 
1414
  reloc_count = *reloc_count_ptr;
1415
  relocs = *relocs_ptr;
1416
  for (i = 0; i < reloc_count; i++)
1417
    {
1418
      arelent *rel;
1419
      asymbol *sym;
1420
      bfd_size_type address;
1421
      bfd_vma addend;
1422
 
1423
      rel = *relocs++;
1424
      sym = *rel->sym_ptr_ptr;
1425
 
1426
      /* We're moving the relocs from the input section to the output
1427
         section, so we must adjust the address accordingly.  */
1428
      address = rel->address;
1429
      rel->address += insec->output_offset;
1430
 
1431
      /* Note that no serious harm will ensue if we fail to change a
1432
         reloc.  The backend will fail when writing out the reloc.  */
1433
 
1434
      /* Make sure this reloc is within the data we have.  We use only
1435
         4 byte relocs here, so we insist on having 4 bytes.  */
1436
      if (address + 4 > contents_size)
1437
        continue;
1438
 
1439
      /* A PC relative reloc entirely within a single section is
1440
         completely unnecessary.  This can be generated by ld -r.  */
1441
      if (sym == insec->symbol
1442
          && rel->howto != NULL
1443
          && rel->howto->pc_relative
1444
          && ! rel->howto->pcrel_offset)
1445
        {
1446
          --*reloc_count_ptr;
1447
          --relocs;
1448
          memmove (relocs, relocs + 1,
1449
                   (size_t) ((reloc_count - i) * sizeof (arelent *)));
1450
          continue;
1451
        }
1452
 
1453
      /* Get the amount the relocation will add in.  */
1454
      addend = rel->addend + sym->value;
1455
 
1456
      /* NetWare doesn't support PC relative relocs against defined
1457
         symbols, so we have to eliminate them by doing the relocation
1458
         now.  We can only do this if the reloc is within a single
1459
         section.  */
1460
      if (rel->howto != NULL
1461
          && rel->howto->pc_relative
1462
          && bfd_get_section (sym) == insec->output_section)
1463
        {
1464
          bfd_vma val;
1465
 
1466
          if (rel->howto->pcrel_offset)
1467
            addend -= address;
1468
 
1469
          val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1470
          val += addend;
1471
          bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1472
 
1473
          --*reloc_count_ptr;
1474
          --relocs;
1475
          memmove (relocs, relocs + 1,
1476
                   (size_t) ((reloc_count - i) * sizeof (arelent *)));
1477
          continue;
1478
        }
1479
 
1480
      /* NetWare doesn't support reloc addends, so we get rid of them
1481
         here by simply adding them into the object data.  We handle
1482
         the symbol value, if any, the same way.  */
1483
      if (addend != 0
1484
          && rel->howto != NULL
1485
          && rel->howto->rightshift == 0
1486
          && rel->howto->size == 2
1487
          && rel->howto->bitsize == 32
1488
          && rel->howto->bitpos == 0
1489
          && rel->howto->src_mask == 0xffffffff
1490
          && rel->howto->dst_mask == 0xffffffff)
1491
        {
1492
          bfd_vma val;
1493
 
1494
          val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1495
          val += addend;
1496
          bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1497
 
1498
          /* Adjust the reloc for the changes we just made.  */
1499
          rel->addend = 0;
1500
          if (! bfd_is_und_section (bfd_get_section (sym)))
1501
            rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
1502
        }
1503
 
1504
      /* NetWare uses a reloc with pcrel_offset set.  We adjust
1505
         pc_relative relocs accordingly.  We are going to change the
1506
         howto field, so we can only do this if the current one is
1507
         compatible.  We should check that special_function is NULL
1508
         here, but at the moment coff-i386 uses a special_function
1509
         which does not affect what we are doing here.  */
1510
      if (rel->howto != NULL
1511
          && rel->howto->pc_relative
1512
          && ! rel->howto->pcrel_offset
1513
          && rel->howto->rightshift == 0
1514
          && rel->howto->size == 2
1515
          && rel->howto->bitsize == 32
1516
          && rel->howto->bitpos == 0
1517
          && rel->howto->src_mask == 0xffffffff
1518
          && rel->howto->dst_mask == 0xffffffff)
1519
        {
1520
          bfd_vma val;
1521
 
1522
          /* When pcrel_offset is not set, it means that the negative
1523
             of the address of the memory location is stored in the
1524
             memory location.  We must add it back in.  */
1525
          val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1526
          val += address;
1527
          bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
1528
 
1529
          /* We must change to a new howto.  */
1530
          rel->howto = &nlm_i386_pcrel_howto;
1531
        }
1532
    }
1533
}
1534
 
1535
#endif /* NLMCONV_I386 */
1536
 
1537
#ifdef NLMCONV_ALPHA
1538
 
1539
/* On the Alpha the first reloc for every section must be a special
1540
   relocs which hold the GP address.  Also, the first reloc in the
1541
   file must be a special reloc which holds the address of the .lita
1542
   section.  */
1543
 
1544
static reloc_howto_type nlm32_alpha_nw_howto =
1545
  HOWTO (ALPHA_R_NW_RELOC,      /* type */
1546
         0,                      /* rightshift */
1547
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
1548
         0,                      /* bitsize */
1549
         FALSE,                 /* pc_relative */
1550
         0,                      /* bitpos */
1551
         complain_overflow_dont, /* complain_on_overflow */
1552
         0,                      /* special_function */
1553
         "NW_RELOC",            /* name */
1554
         FALSE,                 /* partial_inplace */
1555
         0,                      /* src_mask */
1556
         0,                      /* dst_mask */
1557
         FALSE);                /* pcrel_offset */
1558
 
1559
static void
1560
alpha_mangle_relocs (bfd *outbfd, asection *insec,
1561
                     arelent ***relocs_ptr, long *reloc_count_ptr,
1562
                     char *contents ATTRIBUTE_UNUSED,
1563
                     bfd_size_type contents_size ATTRIBUTE_UNUSED)
1564
{
1565
  long old_reloc_count;
1566
  arelent **old_relocs;
1567
  arelent **relocs;
1568
 
1569
  old_reloc_count = *reloc_count_ptr;
1570
  old_relocs = *relocs_ptr;
1571
  relocs = (arelent **) xmalloc ((old_reloc_count + 3) * sizeof (arelent *));
1572
  *relocs_ptr = relocs;
1573
 
1574
  if (nlm_alpha_backend_data (outbfd)->lita_address == 0)
1575
    {
1576
      bfd *inbfd;
1577
      asection *lita_section;
1578
 
1579
      inbfd = insec->owner;
1580
      lita_section = bfd_get_section_by_name (inbfd, _LITA);
1581
      if (lita_section != (asection *) NULL)
1582
        {
1583
          nlm_alpha_backend_data (outbfd)->lita_address =
1584
            bfd_get_section_vma (inbfd, lita_section);
1585
          nlm_alpha_backend_data (outbfd)->lita_size =
1586
            bfd_section_size (inbfd, lita_section);
1587
        }
1588
      else
1589
        {
1590
          /* Avoid outputting this reloc again.  */
1591
          nlm_alpha_backend_data (outbfd)->lita_address = 4;
1592
        }
1593
 
1594
      *relocs = (arelent *) xmalloc (sizeof (arelent));
1595
      (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1596
      (*relocs)->address = nlm_alpha_backend_data (outbfd)->lita_address;
1597
      (*relocs)->addend = nlm_alpha_backend_data (outbfd)->lita_size + 1;
1598
      (*relocs)->howto = &nlm32_alpha_nw_howto;
1599
      ++relocs;
1600
      ++(*reloc_count_ptr);
1601
    }
1602
 
1603
  /* Get the GP value from bfd.  */
1604
  if (nlm_alpha_backend_data (outbfd)->gp == 0)
1605
    nlm_alpha_backend_data (outbfd)->gp =
1606
      bfd_ecoff_get_gp_value (insec->owner);
1607
 
1608
  *relocs = (arelent *) xmalloc (sizeof (arelent));
1609
  (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1610
  (*relocs)->address = nlm_alpha_backend_data (outbfd)->gp;
1611
  (*relocs)->addend = 0;
1612
  (*relocs)->howto = &nlm32_alpha_nw_howto;
1613
  ++relocs;
1614
  ++(*reloc_count_ptr);
1615
 
1616
  memcpy (relocs, old_relocs, (size_t) old_reloc_count * sizeof (arelent *));
1617
  relocs[old_reloc_count] = (arelent *) NULL;
1618
 
1619
  free (old_relocs);
1620
 
1621
  if (insec->output_offset != 0)
1622
    {
1623
      bfd_size_type i;
1624
 
1625
      for (i = 0; i < (bfd_size_type) old_reloc_count; i++, relocs++)
1626
        (*relocs)->address += insec->output_offset;
1627
    }
1628
}
1629
 
1630
#endif /* NLMCONV_ALPHA */
1631
 
1632
#ifdef NLMCONV_POWERPC
1633
 
1634
/* We keep a linked list of stubs which we must build.  Because BFD
1635
   requires us to know the sizes of all sections before we can set the
1636
   contents of any, we must figure out which stubs we want to build
1637
   before we can actually build any of them.  */
1638
 
1639
struct powerpc_stub
1640
{
1641
  /* Next stub in linked list.  */
1642
  struct powerpc_stub *next;
1643
 
1644
  /* Symbol whose value is the start of the stub.  This is a symbol
1645
     whose name begins with `.'.  */
1646
  asymbol *start;
1647
 
1648
  /* Symbol we are going to create a reloc against.  This is a symbol
1649
     with the same name as START but without the leading `.'.  */
1650
  asymbol *reloc;
1651
 
1652
  /* The TOC index for this stub.  This is the index into the TOC
1653
     section at which the reloc is created.  */
1654
  unsigned int toc_index;
1655
};
1656
 
1657
/* The linked list of stubs.  */
1658
 
1659
static struct powerpc_stub *powerpc_stubs;
1660
 
1661
/* This is what a stub looks like.  The first instruction will get
1662
   adjusted with the correct TOC index.  */
1663
 
1664
static unsigned long powerpc_stub_insns[] =
1665
{
1666
  0x81820000,           /* lwz   r12,0(r2) */
1667
  0x90410014,           /* stw   r2,20(r1) */
1668
  0x800c0000,           /* lwz   r0,0(r12) */
1669
  0x804c0004,           /* lwz   r2,r(r12) */
1670
  0x7c0903a6,           /* mtctr r0 */
1671
  0x4e800420,           /* bctr */
1672
  0,                     /* Traceback table.  */
1673
  0xc8000,
1674
 
1675
};
1676
 
1677
#define POWERPC_STUB_INSN_COUNT \
1678
  (sizeof powerpc_stub_insns / sizeof powerpc_stub_insns[0])
1679
 
1680
#define POWERPC_STUB_SIZE (4 * POWERPC_STUB_INSN_COUNT)
1681
 
1682
/* Each stub uses a four byte TOC entry.  */
1683
#define POWERPC_STUB_TOC_ENTRY_SIZE (4)
1684
 
1685
/* The original size of the .got section.  */
1686
static bfd_size_type powerpc_initial_got_size;
1687
 
1688
/* Look for all undefined symbols beginning with `.', and prepare to
1689
   build a stub for each one.  */
1690
 
1691
static void
1692
powerpc_build_stubs (bfd *inbfd, bfd *outbfd ATTRIBUTE_UNUSED,
1693
                     asymbol ***symbols_ptr, long *symcount_ptr)
1694
{
1695
  asection *stub_sec;
1696
  asection *got_sec;
1697
  unsigned int got_base;
1698
  long i;
1699
  long symcount;
1700
  long stubcount;
1701
 
1702
  /* Make a section to hold stubs.  We don't set SEC_HAS_CONTENTS for
1703
     the section to prevent copy_sections from reading from it.  */
1704
  stub_sec = bfd_make_section (inbfd, ".stubs");
1705
  if (stub_sec == (asection *) NULL
1706
      || ! bfd_set_section_flags (inbfd, stub_sec,
1707
                                  (SEC_CODE
1708
                                   | SEC_RELOC
1709
                                   | SEC_ALLOC
1710
                                   | SEC_LOAD))
1711
      || ! bfd_set_section_alignment (inbfd, stub_sec, 2))
1712
    bfd_fatal (".stubs");
1713
 
1714
  /* Get the TOC section, which is named .got.  */
1715
  got_sec = bfd_get_section_by_name (inbfd, ".got");
1716
  if (got_sec == (asection *) NULL)
1717
    {
1718
      got_sec = bfd_make_section (inbfd, ".got");
1719
      if (got_sec == (asection *) NULL
1720
          || ! bfd_set_section_flags (inbfd, got_sec,
1721
                                      (SEC_DATA
1722
                                       | SEC_RELOC
1723
                                       | SEC_ALLOC
1724
                                       | SEC_LOAD
1725
                                       | SEC_HAS_CONTENTS))
1726
          || ! bfd_set_section_alignment (inbfd, got_sec, 2))
1727
        bfd_fatal (".got");
1728
    }
1729
 
1730
  powerpc_initial_got_size = bfd_section_size (inbfd, got_sec);
1731
  got_base = powerpc_initial_got_size;
1732
  got_base = (got_base + 3) &~ 3;
1733
 
1734
  stubcount = 0;
1735
 
1736
  symcount = *symcount_ptr;
1737
  for (i = 0; i < symcount; i++)
1738
    {
1739
      asymbol *sym;
1740
      asymbol *newsym;
1741
      char *newname;
1742
      struct powerpc_stub *item;
1743
 
1744
      sym = (*symbols_ptr)[i];
1745
 
1746
      /* We must make a stub for every undefined symbol whose name
1747
         starts with '.'.  */
1748
      if (bfd_asymbol_name (sym)[0] != '.'
1749
          || ! bfd_is_und_section (bfd_get_section (sym)))
1750
        continue;
1751
 
1752
      /* Make a new undefined symbol with the same name but without
1753
         the leading `.'.  */
1754
      newsym = xmalloc (sizeof (asymbol));
1755
      *newsym = *sym;
1756
      newname = xmalloc (strlen (bfd_asymbol_name (sym)));
1757
      strcpy (newname, bfd_asymbol_name (sym) + 1);
1758
      newsym->name = newname;
1759
 
1760
      /* Define the `.' symbol to be in the stub section.  */
1761
      sym->section = stub_sec;
1762
      sym->value = stubcount * POWERPC_STUB_SIZE;
1763
      /* We set the BSF_DYNAMIC flag here so that we can check it when
1764
         we are mangling relocs.  FIXME: This is a hack.  */
1765
      sym->flags = BSF_LOCAL | BSF_DYNAMIC;
1766
 
1767
      /* Add this stub to the linked list.  */
1768
      item = (struct powerpc_stub *) xmalloc (sizeof (struct powerpc_stub));
1769
      item->start = sym;
1770
      item->reloc = newsym;
1771
      item->toc_index = got_base + stubcount * POWERPC_STUB_TOC_ENTRY_SIZE;
1772
 
1773
      item->next = powerpc_stubs;
1774
      powerpc_stubs = item;
1775
 
1776
      ++stubcount;
1777
    }
1778
 
1779
  if (stubcount > 0)
1780
    {
1781
      asymbol **s;
1782
      struct powerpc_stub *l;
1783
 
1784
      /* Add the new symbols we just created to the symbol table.  */
1785
      *symbols_ptr = (asymbol **) xrealloc ((char *) *symbols_ptr,
1786
                                            ((symcount + stubcount)
1787
                                             * sizeof (asymbol)));
1788
      *symcount_ptr += stubcount;
1789
      s = &(*symbols_ptr)[symcount];
1790
      for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1791
        *s++ = l->reloc;
1792
 
1793
      /* Set the size of the .stubs section and increase the size of
1794
         the .got section.  */
1795
      if (! bfd_set_section_size (inbfd, stub_sec,
1796
                                  stubcount * POWERPC_STUB_SIZE)
1797
          || ! bfd_set_section_size (inbfd, got_sec,
1798
                                     (got_base
1799
                                      + (stubcount
1800
                                         * POWERPC_STUB_TOC_ENTRY_SIZE))))
1801
        bfd_fatal (_("stub section sizes"));
1802
    }
1803
}
1804
 
1805
/* Resolve all the stubs for PowerPC NetWare.  We fill in the contents
1806
   of the output section, and create new relocs in the TOC.  */
1807
 
1808
static void
1809
powerpc_resolve_stubs (bfd *inbfd, bfd *outbfd)
1810
{
1811
  bfd_byte buf[POWERPC_STUB_SIZE];
1812
  unsigned int i;
1813
  unsigned int stubcount;
1814
  arelent **relocs;
1815
  asection *got_sec;
1816
  arelent **r;
1817
  struct powerpc_stub *l;
1818
 
1819
  if (powerpc_stubs == (struct powerpc_stub *) NULL)
1820
    return;
1821
 
1822
  for (i = 0; i < POWERPC_STUB_INSN_COUNT; i++)
1823
    bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[i], buf + i * 4);
1824
 
1825
  got_sec = bfd_get_section_by_name (inbfd, ".got");
1826
  assert (got_sec != (asection *) NULL);
1827
  assert (got_sec->output_section->orelocation == (arelent **) NULL);
1828
 
1829
  stubcount = 0;
1830
  for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1831
    ++stubcount;
1832
  relocs = (arelent **) xmalloc (stubcount * sizeof (arelent *));
1833
 
1834
  r = relocs;
1835
  for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1836
    {
1837
      arelent *reloc;
1838
 
1839
      /* Adjust the first instruction to use the right TOC index.  */
1840
      bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[0] + l->toc_index, buf);
1841
 
1842
      /* Write this stub out.  */
1843
      if (! bfd_set_section_contents (outbfd,
1844
                                      bfd_get_section (l->start),
1845
                                      buf,
1846
                                      l->start->value,
1847
                                      POWERPC_STUB_SIZE))
1848
        bfd_fatal (_("writing stub"));
1849
 
1850
      /* Create a new reloc for the TOC entry.  */
1851
      reloc = (arelent *) xmalloc (sizeof (arelent));
1852
      reloc->sym_ptr_ptr = &l->reloc;
1853
      reloc->address = l->toc_index + got_sec->output_offset;
1854
      reloc->addend = 0;
1855
      reloc->howto = bfd_reloc_type_lookup (inbfd, BFD_RELOC_32);
1856
 
1857
      *r++ = reloc;
1858
    }
1859
 
1860
  bfd_set_reloc (outbfd, got_sec->output_section, relocs, stubcount);
1861
}
1862
 
1863
/* Adjust relocation entries for PowerPC NetWare.  We do not output
1864
   TOC relocations.  The object code already contains the offset from
1865
   the TOC pointer.  When the function is called, the TOC register,
1866
   r2, will be set to the correct TOC value, so there is no need for
1867
   any further reloc.  */
1868
 
1869
static void
1870
powerpc_mangle_relocs (bfd *outbfd, asection *insec,
1871
                       arelent ***relocs_ptr,
1872
                       long *reloc_count_ptr, char *contents,
1873
                       bfd_size_type contents_size ATTRIBUTE_UNUSED)
1874
{
1875
  reloc_howto_type *toc_howto;
1876
  long reloc_count;
1877
  arelent **relocs;
1878
  long i;
1879
 
1880
  toc_howto = bfd_reloc_type_lookup (insec->owner, BFD_RELOC_PPC_TOC16);
1881
  if (toc_howto == (reloc_howto_type *) NULL)
1882
    abort ();
1883
 
1884
  /* If this is the .got section, clear out all the contents beyond
1885
     the initial size.  We must do this here because copy_sections is
1886
     going to write out whatever we return in the contents field.  */
1887
  if (strcmp (bfd_get_section_name (insec->owner, insec), ".got") == 0)
1888
    memset (contents + powerpc_initial_got_size, 0,
1889
            (size_t) (bfd_get_section_size (insec) - powerpc_initial_got_size));
1890
 
1891
  reloc_count = *reloc_count_ptr;
1892
  relocs = *relocs_ptr;
1893
  for (i = 0; i < reloc_count; i++)
1894
    {
1895
      arelent *rel;
1896
      asymbol *sym;
1897
      bfd_vma sym_value;
1898
 
1899
      rel = *relocs++;
1900
      sym = *rel->sym_ptr_ptr;
1901
 
1902
      /* Convert any relocs against the .bss section into relocs
1903
         against the .data section.  */
1904
      if (strcmp (bfd_get_section_name (outbfd, bfd_get_section (sym)),
1905
                  NLM_UNINITIALIZED_DATA_NAME) == 0)
1906
        {
1907
          asection *datasec;
1908
 
1909
          datasec = bfd_get_section_by_name (outbfd,
1910
                                             NLM_INITIALIZED_DATA_NAME);
1911
          if (datasec != NULL)
1912
            {
1913
              rel->addend += (bfd_get_section_vma (outbfd,
1914
                                                   bfd_get_section (sym))
1915
                              + sym->value);
1916
              rel->sym_ptr_ptr = datasec->symbol_ptr_ptr;
1917
              sym = *rel->sym_ptr_ptr;
1918
            }
1919
        }
1920
 
1921
      /* We must be able to resolve all PC relative relocs at this
1922
         point.  If we get a branch to an undefined symbol we build a
1923
         stub, since NetWare will resolve undefined symbols into a
1924
         pointer to a function descriptor.  */
1925
      if (rel->howto->pc_relative)
1926
        {
1927
          /* This check for whether a symbol is in the same section as
1928
             the reloc will be wrong if there is a PC relative reloc
1929
             between two sections both of which were placed in the
1930
             same output section.  This should not happen.  */
1931
          if (bfd_get_section (sym) != insec->output_section)
1932
            non_fatal (_("unresolved PC relative reloc against %s"),
1933
                       bfd_asymbol_name (sym));
1934
          else
1935
            {
1936
              bfd_vma val;
1937
 
1938
              assert (rel->howto->size == 2 && rel->howto->pcrel_offset);
1939
              val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address);
1940
              val = ((val &~ rel->howto->dst_mask)
1941
                     | (((val & rel->howto->src_mask)
1942
                         + (sym->value - rel->address)
1943
                         + rel->addend)
1944
                        & rel->howto->dst_mask));
1945
              bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
1946
 
1947
              /* If this reloc is against an stubbed symbol and the
1948
                 next instruction is
1949
                     cror 31,31,31
1950
                 then we replace the next instruction with
1951
                     lwz  r2,20(r1)
1952
                 This reloads the TOC pointer after a stub call.  */
1953
              if (bfd_asymbol_name (sym)[0] == '.'
1954
                  && (sym->flags & BSF_DYNAMIC) != 0
1955
                  && (bfd_get_32 (outbfd,
1956
                                  (bfd_byte *) contents + rel->address + 4)
1957
                      == 0x4ffffb82)) /* cror 31,31,31 */
1958
                bfd_put_32 (outbfd, (bfd_vma) 0x80410014, /* lwz r2,20(r1) */
1959
                            (bfd_byte *) contents + rel->address + 4);
1960
 
1961
              --*reloc_count_ptr;
1962
              --relocs;
1963
              memmove (relocs, relocs + 1,
1964
                       (size_t) ((reloc_count - 1) * sizeof (arelent *)));
1965
              continue;
1966
            }
1967
        }
1968
 
1969
      /* When considering a TOC reloc, we do not want to include the
1970
         symbol value.  The symbol will be start of the TOC section
1971
         (which is named .got).  We do want to include the addend.  */
1972
      if (rel->howto == toc_howto)
1973
        sym_value = 0;
1974
      else
1975
        sym_value = sym->value;
1976
 
1977
      /* If this is a relocation against a symbol with a value, or
1978
         there is a reloc addend, we need to update the addend in the
1979
         object file.  */
1980
      if (sym_value + rel->addend != 0)
1981
        {
1982
          bfd_vma val;
1983
 
1984
          switch (rel->howto->size)
1985
            {
1986
            case 1:
1987
              val = bfd_get_16 (outbfd,
1988
                                (bfd_byte *) contents + rel->address);
1989
              val = ((val &~ rel->howto->dst_mask)
1990
                     | (((val & rel->howto->src_mask)
1991
                         + sym_value
1992
                         + rel->addend)
1993
                        & rel->howto->dst_mask));
1994
              if ((bfd_signed_vma) val < - 0x8000
1995
                  || (bfd_signed_vma) val >= 0x8000)
1996
                non_fatal (_("overflow when adjusting relocation against %s"),
1997
                           bfd_asymbol_name (sym));
1998
              bfd_put_16 (outbfd, val, (bfd_byte *) contents + rel->address);
1999
              break;
2000
 
2001
            case 2:
2002
              val = bfd_get_32 (outbfd,
2003
                                (bfd_byte *) contents + rel->address);
2004
              val = ((val &~ rel->howto->dst_mask)
2005
                     | (((val & rel->howto->src_mask)
2006
                         + sym_value
2007
                         + rel->addend)
2008
                        & rel->howto->dst_mask));
2009
              bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
2010
              break;
2011
 
2012
            default:
2013
              abort ();
2014
            }
2015
 
2016
          if (! bfd_is_und_section (bfd_get_section (sym)))
2017
            rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
2018
          rel->addend = 0;
2019
        }
2020
 
2021
      /* Now that we have incorporated the addend, remove any TOC
2022
         relocs.  */
2023
      if (rel->howto == toc_howto)
2024
        {
2025
          --*reloc_count_ptr;
2026
          --relocs;
2027
          memmove (relocs, relocs + 1,
2028
                   (size_t) ((reloc_count - i) * sizeof (arelent *)));
2029
          continue;
2030
        }
2031
 
2032
      rel->address += insec->output_offset;
2033
    }
2034
}
2035
 
2036
#endif /* NLMCONV_POWERPC */
2037
 
2038
/* Name of linker.  */
2039
#ifndef LD_NAME
2040
#define LD_NAME "ld"
2041
#endif
2042
 
2043
/* The user has specified several input files.  Invoke the linker to
2044
   link them all together, and convert and delete the resulting output
2045
   file.  */
2046
 
2047
static char *
2048
link_inputs (struct string_list *inputs, char *ld, char * map_file)
2049
{
2050
  size_t c;
2051
  struct string_list *q;
2052
  char **argv;
2053
  size_t i;
2054
  int pid;
2055
  int status;
2056
  char *errfmt;
2057
  char *errarg;
2058
 
2059
  c = 0;
2060
  for (q = inputs; q != NULL; q = q->next)
2061
    ++c;
2062
 
2063
  argv = (char **) alloca ((c + 7) * sizeof (char *));
2064
 
2065
#ifndef __MSDOS__
2066
  if (ld == NULL)
2067
    {
2068
      char *p;
2069
 
2070
      /* Find the linker to invoke based on how nlmconv was run.  */
2071
      p = program_name + strlen (program_name);
2072
      while (p != program_name)
2073
        {
2074
          if (p[-1] == '/')
2075
            {
2076
              ld = (char *) xmalloc (p - program_name + strlen (LD_NAME) + 1);
2077
              memcpy (ld, program_name, p - program_name);
2078
              strcpy (ld + (p - program_name), LD_NAME);
2079
              break;
2080
            }
2081
          --p;
2082
        }
2083
    }
2084
#endif
2085
 
2086
  if (ld == NULL)
2087
    ld = (char *) LD_NAME;
2088
 
2089
  unlink_on_exit = make_temp_file (".O");
2090
 
2091
  argv[0] = ld;
2092
  argv[1] = (char *) "-Ur";
2093
  argv[2] = (char *) "-o";
2094
  argv[3] = unlink_on_exit;
2095
  /* If we have been given the name of a mapfile and that
2096
     name is not 'stderr' then pass it on to the linker.  */
2097
  if (map_file
2098
      && * map_file
2099
      && strcmp (map_file, "stderr") == 0)
2100
    {
2101
      argv[4] = (char *) "-Map";
2102
      argv[5] = map_file;
2103
      i = 6;
2104
    }
2105
  else
2106
    i = 4;
2107
 
2108
  for (q = inputs; q != NULL; q = q->next, i++)
2109
    argv[i] = q->string;
2110
  argv[i] = NULL;
2111
 
2112
  if (debug)
2113
    {
2114
      for (i = 0; argv[i] != NULL; i++)
2115
        fprintf (stderr, " %s", argv[i]);
2116
      fprintf (stderr, "\n");
2117
    }
2118
 
2119
  pid = pexecute (ld, argv, program_name, (char *) NULL, &errfmt, &errarg,
2120
                  PEXECUTE_SEARCH | PEXECUTE_ONE);
2121
  if (pid == -1)
2122
    {
2123
      fprintf (stderr, _("%s: execution of %s failed: "), program_name, ld);
2124
      fprintf (stderr, errfmt, errarg);
2125
      unlink (unlink_on_exit);
2126
      exit (1);
2127
    }
2128
 
2129
  if (pwait (pid, &status, 0) < 0)
2130
    {
2131
      perror ("pwait");
2132
      unlink (unlink_on_exit);
2133
      exit (1);
2134
    }
2135
 
2136
  if (status != 0)
2137
    {
2138
      non_fatal (_("Execution of %s failed"), ld);
2139
      unlink (unlink_on_exit);
2140
      exit (1);
2141
    }
2142
 
2143
  return unlink_on_exit;
2144
}

powered by: WebSVN 2.1.0

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