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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [bfd/] [nlm32-ppc.c] - Blame information for rev 1772

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

Line No. Rev Author Line
1 104 markom
/* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
2
   Copyright (C) 1994, 1995, 1999 Free Software Foundation, Inc.
3
 
4
This file is part of BFD, the Binary File Descriptor library.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
 
20
#include "bfd.h"
21
#include "sysdep.h"
22
#include "libbfd.h"
23
 
24
/* The format of a PowerPC NLM changed.  Define OLDFORMAT to get the
25
   old format.  */
26
 
27
#define ARCH_SIZE 32
28
 
29
#include "nlm/ppc-ext.h"
30
#define Nlm_External_Fixed_Header       Nlm32_powerpc_External_Fixed_Header
31
 
32
#include "libnlm.h"
33
 
34
#ifdef OLDFORMAT
35
static boolean nlm_powerpc_backend_object_p
36
  PARAMS ((bfd *));
37
static boolean nlm_powerpc_write_prefix
38
  PARAMS ((bfd *));
39
#endif
40
 
41
static boolean nlm_powerpc_read_reloc
42
  PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
43
static boolean nlm_powerpc_mangle_relocs
44
  PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
45
static boolean nlm_powerpc_read_import
46
  PARAMS ((bfd *, nlmNAME(symbol_type) *));
47
 
48
#ifdef OLDFORMAT
49
static boolean nlm_powerpc_write_reloc
50
  PARAMS ((bfd *, asection *, arelent *, int));
51
#endif
52
 
53
static boolean nlm_powerpc_write_import
54
  PARAMS ((bfd *, asection *, arelent *));
55
static boolean nlm_powerpc_write_external
56
  PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
57
 
58
#ifndef OLDFORMAT
59
static boolean nlm_powerpc_set_public_section
60
  PARAMS ((bfd *, nlmNAME(symbol_type) *));
61
static bfd_vma nlm_powerpc_get_public_offset
62
  PARAMS ((bfd *, asymbol *));
63
#endif
64
 
65
#ifdef OLDFORMAT
66
 
67
/* The prefix header is only used in the old format.  */
68
 
69
/* PowerPC NLM's have a prefix header before the standard NLM.  This
70
   function reads it in, verifies the version, and seeks the bfd to
71
   the location before the regular NLM header.  */
72
 
73
static boolean
74
nlm_powerpc_backend_object_p (abfd)
75
     bfd *abfd;
76
{
77
  struct nlm32_powerpc_external_prefix_header s;
78
 
79
  if (bfd_read ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
80
    return false;
81
 
82
  if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0
83
      || bfd_h_get_32 (abfd, s.headerVersion) != NLM32_POWERPC_HEADER_VERSION)
84
    return false;
85
 
86
  return true;
87
}
88
 
89
/* Write out the prefix.  */
90
 
91
static boolean
92
nlm_powerpc_write_prefix (abfd)
93
     bfd *abfd;
94
{
95
  struct nlm32_powerpc_external_prefix_header s;
96
 
97
  memset (&s, 0, sizeof s);
98
  memcpy (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature);
99
  bfd_h_put_32 (abfd, (bfd_vma) NLM32_POWERPC_HEADER_VERSION, s.headerVersion);
100
  bfd_h_put_32 (abfd, (bfd_vma) 0, s.origins);
101
 
102
  /* FIXME: What should we do about the date?  */
103
 
104
  if (bfd_write ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
105
    return false;
106
 
107
  return true;
108
}
109
 
110
#endif /* OLDFORMAT */
111
 
112
#ifndef OLDFORMAT
113
 
114
/* There is only one type of reloc in a PowerPC NLM.  */
115
 
116
static reloc_howto_type nlm_powerpc_howto =
117
  HOWTO (0,                      /* type */
118
         0,                      /* rightshift */
119
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
120
         32,                    /* bitsize */
121
         false,                 /* pc_relative */
122
         0,                      /* bitpos */
123
         complain_overflow_bitfield, /* complain_on_overflow */
124
         0,                      /* special_function */
125
         "32",                  /* name */
126
         true,                  /* partial_inplace */
127
         0xffffffff,            /* src_mask */
128
         0xffffffff,            /* dst_mask */
129
         false);                /* pcrel_offset */
130
 
131
/* Read a PowerPC NLM reloc.  */
132
 
133
static boolean
134
nlm_powerpc_read_reloc (abfd, sym, secp, rel)
135
     bfd *abfd;
136
     nlmNAME(symbol_type) *sym;
137
     asection **secp;
138
     arelent *rel;
139
{
140
  bfd_byte temp[4];
141
  bfd_vma val;
142
  const char *name;
143
 
144
  if (bfd_read (temp, sizeof (temp), 1, abfd) != sizeof (temp))
145
    return false;
146
 
147
  val = bfd_get_32 (abfd, temp);
148
 
149
  /* The value is a word offset into either the code or data segment.
150
     This is the location which needs to be adjusted.
151
 
152
     The high bit is 0 if the value is an offset into the data
153
     segment, or 1 if the value is an offset into the text segment.
154
 
155
     If this is a relocation fixup rather than an imported symbol (the
156
     sym argument is NULL), then the second most significant bit is 0
157
     if the address of the data segment should be added to the
158
     location addressed by the value, or 1 if the address of the text
159
     segment should be added.
160
 
161
     If this is an imported symbol, the second most significant bit is
162
     not used and must be 0.  */
163
 
164
  if ((val & NLM_HIBIT) == 0)
165
    name = NLM_INITIALIZED_DATA_NAME;
166
  else
167
    {
168
      name = NLM_CODE_NAME;
169
      val &=~ NLM_HIBIT;
170
    }
171
  *secp = bfd_get_section_by_name (abfd, name);
172
 
173
  if (sym == NULL)
174
    {
175
      if ((val & (NLM_HIBIT >> 1)) == 0)
176
        name = NLM_INITIALIZED_DATA_NAME;
177
      else
178
        {
179
          name = NLM_CODE_NAME;
180
          val &=~ (NLM_HIBIT >> 1);
181
        }
182
      rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
183
    }
184
 
185
  rel->howto = &nlm_powerpc_howto;
186
 
187
  rel->address = val << 2;
188
  rel->addend = 0;
189
 
190
  return true;
191
}
192
 
193
#else /* OLDFORMAT */
194
 
195
/* This reloc handling is only applicable to the old format.  */
196
 
197
/* How to process the various reloc types.  PowerPC NLMs use XCOFF
198
   reloc types, and I have just copied the XCOFF reloc table here.  */
199
 
200
static reloc_howto_type nlm_powerpc_howto_table[] =
201
{
202
  /* Standard 32 bit relocation.  */
203
  HOWTO (0,                      /* type */
204
         0,                      /* rightshift */
205
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
206
         32,                    /* bitsize */
207
         false,                 /* pc_relative */
208
         0,                      /* bitpos */
209
         complain_overflow_bitfield, /* complain_on_overflow */
210
         0,                      /* special_function */
211
         "R_POS",               /* name */
212
         true,                  /* partial_inplace */
213
         0xffffffff,            /* src_mask */
214
         0xffffffff,            /* dst_mask */
215
         false),                /* pcrel_offset */
216
 
217
  /* 32 bit relocation, but store negative value.  */
218
  HOWTO (1,                     /* type */
219
         0,                      /* rightshift */
220
         -2,                    /* size (0 = byte, 1 = short, 2 = long) */
221
         32,                    /* bitsize */
222
         false,                 /* pc_relative */
223
         0,                      /* bitpos */
224
         complain_overflow_bitfield, /* complain_on_overflow */
225
         0,                      /* special_function */
226
         "R_NEG",               /* name */
227
         true,                  /* partial_inplace */
228
         0xffffffff,            /* src_mask */
229
         0xffffffff,            /* dst_mask */
230
         false),                /* pcrel_offset */
231
 
232
  /* 32 bit PC relative relocation.  */
233
  HOWTO (2,                     /* type */
234
         0,                      /* rightshift */
235
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
236
         32,                    /* bitsize */
237
         true,                  /* pc_relative */
238
         0,                      /* bitpos */
239
         complain_overflow_signed, /* complain_on_overflow */
240
         0,                      /* special_function */
241
         "R_REL",               /* name */
242
         true,                  /* partial_inplace */
243
         0xffffffff,            /* src_mask */
244
         0xffffffff,            /* dst_mask */
245
         false),                /* pcrel_offset */
246
 
247
  /* 16 bit TOC relative relocation.  */
248
  HOWTO (3,                     /* type */
249
         0,                      /* rightshift */
250
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
251
         16,                    /* bitsize */
252
         false,                 /* pc_relative */
253
         0,                      /* bitpos */
254
         complain_overflow_signed, /* complain_on_overflow */
255
         0,                      /* special_function */
256
         "R_TOC",               /* name */
257
         true,                  /* partial_inplace */
258
         0xffff,                /* src_mask */
259
         0xffff,                /* dst_mask */
260
         false),                /* pcrel_offset */
261
 
262
  /* I don't really know what this is.  */
263
  HOWTO (4,                     /* type */
264
         1,                     /* rightshift */
265
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
266
         32,                    /* bitsize */
267
         false,                 /* pc_relative */
268
         0,                      /* bitpos */
269
         complain_overflow_bitfield, /* complain_on_overflow */
270
         0,                      /* special_function */
271
         "R_RTB",               /* name */
272
         true,                  /* partial_inplace */
273
         0xffffffff,            /* src_mask */
274
         0xffffffff,            /* dst_mask */
275
         false),                /* pcrel_offset */
276
 
277
  /* External TOC relative symbol.  */
278
  HOWTO (5,                     /* type */
279
         0,                      /* rightshift */
280
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
281
         16,                    /* bitsize */
282
         false,                 /* pc_relative */
283
         0,                      /* bitpos */
284
         complain_overflow_bitfield, /* complain_on_overflow */
285
         0,                      /* special_function */
286
         "R_GL",                /* name */
287
         true,                  /* partial_inplace */
288
         0xffff,                /* src_mask */
289
         0xffff,                /* dst_mask */
290
         false),                /* pcrel_offset */
291
 
292
  /* Local TOC relative symbol.  */
293
  HOWTO (6,                     /* type */
294
         0,                      /* rightshift */
295
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
296
         16,                    /* bitsize */
297
         false,                 /* pc_relative */
298
         0,                      /* bitpos */
299
         complain_overflow_bitfield, /* complain_on_overflow */
300
         0,                      /* special_function */
301
         "R_TCL",               /* name */
302
         true,                  /* partial_inplace */
303
         0xffff,                /* src_mask */
304
         0xffff,                /* dst_mask */
305
         false),                /* pcrel_offset */
306
 
307
  { 7 },
308
 
309
  /* Non modifiable absolute branch.  */
310
  HOWTO (8,                     /* type */
311
         0,                      /* rightshift */
312
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
313
         26,                    /* bitsize */
314
         false,                 /* pc_relative */
315
         0,                      /* bitpos */
316
         complain_overflow_bitfield, /* complain_on_overflow */
317
         0,                      /* special_function */
318
         "R_BA",                /* name */
319
         true,                  /* partial_inplace */
320
         0x3fffffc,             /* src_mask */
321
         0x3fffffc,             /* dst_mask */
322
         false),                /* pcrel_offset */
323
 
324
  { 9 },
325
 
326
  /* Non modifiable relative branch.  */
327
  HOWTO (0xa,                   /* type */
328
         0,                      /* rightshift */
329
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
330
         26,                    /* bitsize */
331
         true,                  /* pc_relative */
332
         0,                      /* bitpos */
333
         complain_overflow_signed, /* complain_on_overflow */
334
         0,                      /* special_function */
335
         "R_BR",                /* name */
336
         true,                  /* partial_inplace */
337
         0x3fffffc,             /* src_mask */
338
         0x3fffffc,             /* dst_mask */
339
         false),                /* pcrel_offset */
340
 
341
  { 0xb },
342
 
343
  /* Indirect load.  */
344
  HOWTO (0xc,                   /* type */
345
         0,                      /* rightshift */
346
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
347
         16,                    /* bitsize */
348
         false,                 /* pc_relative */
349
         0,                      /* bitpos */
350
         complain_overflow_bitfield, /* complain_on_overflow */
351
         0,                      /* special_function */
352
         "R_RL",                /* name */
353
         true,                  /* partial_inplace */
354
         0xffff,                /* src_mask */
355
         0xffff,                /* dst_mask */
356
         false),                /* pcrel_offset */
357
 
358
  /* Load address.  */
359
  HOWTO (0xd,                   /* type */
360
         0,                      /* rightshift */
361
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
362
         16,                    /* bitsize */
363
         false,                 /* pc_relative */
364
         0,                      /* bitpos */
365
         complain_overflow_bitfield, /* complain_on_overflow */
366
         0,                      /* special_function */
367
         "R_RLA",               /* name */
368
         true,                  /* partial_inplace */
369
         0xffff,                /* src_mask */
370
         0xffff,                /* dst_mask */
371
         false),                /* pcrel_offset */
372
 
373
  { 0xe },
374
 
375
  /* Non-relocating reference.  */
376
  HOWTO (0xf,                   /* type */
377
         0,                      /* rightshift */
378
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
379
         32,                    /* bitsize */
380
         false,                 /* pc_relative */
381
         0,                      /* bitpos */
382
         complain_overflow_bitfield, /* complain_on_overflow */
383
         0,                      /* special_function */
384
         "R_REF",               /* name */
385
         false,                 /* partial_inplace */
386
         0,                      /* src_mask */
387
         0,              /* dst_mask */
388
         false),                /* pcrel_offset */
389
 
390
  { 0x10 },
391
  { 0x11 },
392
 
393
  /* TOC relative indirect load.  */
394
  HOWTO (0x12,                  /* type */
395
         0,                      /* rightshift */
396
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
397
         16,                    /* bitsize */
398
         false,                 /* pc_relative */
399
         0,                      /* bitpos */
400
         complain_overflow_bitfield, /* complain_on_overflow */
401
         0,                      /* special_function */
402
         "R_TRL",               /* name */
403
         true,                  /* partial_inplace */
404
         0xffff,                /* src_mask */
405
         0xffff,                /* dst_mask */
406
         false),                /* pcrel_offset */
407
 
408
  /* TOC relative load address.  */
409
  HOWTO (0x13,                  /* type */
410
         0,                      /* rightshift */
411
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
412
         16,                    /* bitsize */
413
         false,                 /* pc_relative */
414
         0,                      /* bitpos */
415
         complain_overflow_bitfield, /* complain_on_overflow */
416
         0,                      /* special_function */
417
         "R_TRLA",              /* name */
418
         true,                  /* partial_inplace */
419
         0xffff,                /* src_mask */
420
         0xffff,                /* dst_mask */
421
         false),                /* pcrel_offset */
422
 
423
  /* Modifiable relative branch.  */
424
  HOWTO (0x14,                  /* type */
425
         1,                     /* rightshift */
426
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
427
         32,                    /* bitsize */
428
         false,                 /* pc_relative */
429
         0,                      /* bitpos */
430
         complain_overflow_bitfield, /* complain_on_overflow */
431
         0,                      /* special_function */
432
         "R_RRTBI",             /* name */
433
         true,                  /* partial_inplace */
434
         0xffffffff,            /* src_mask */
435
         0xffffffff,            /* dst_mask */
436
         false),                /* pcrel_offset */
437
 
438
  /* Modifiable absolute branch.  */
439
  HOWTO (0x15,                  /* type */
440
         1,                     /* rightshift */
441
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
442
         32,                    /* bitsize */
443
         false,                 /* pc_relative */
444
         0,                      /* bitpos */
445
         complain_overflow_bitfield, /* complain_on_overflow */
446
         0,                      /* special_function */
447
         "R_RRTBA",             /* name */
448
         true,                  /* partial_inplace */
449
         0xffffffff,            /* src_mask */
450
         0xffffffff,            /* dst_mask */
451
         false),                /* pcrel_offset */
452
 
453
  /* Modifiable call absolute indirect.  */
454
  HOWTO (0x16,                  /* type */
455
         0,                      /* rightshift */
456
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
457
         16,                    /* bitsize */
458
         false,                 /* pc_relative */
459
         0,                      /* bitpos */
460
         complain_overflow_bitfield, /* complain_on_overflow */
461
         0,                      /* special_function */
462
         "R_CAI",               /* name */
463
         true,                  /* partial_inplace */
464
         0xffff,                /* src_mask */
465
         0xffff,                /* dst_mask */
466
         false),                /* pcrel_offset */
467
 
468
  /* Modifiable call relative.  */
469
  HOWTO (0x17,                  /* type */
470
         0,                      /* rightshift */
471
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
472
         16,                    /* bitsize */
473
         false,                 /* pc_relative */
474
         0,                      /* bitpos */
475
         complain_overflow_bitfield, /* complain_on_overflow */
476
         0,                      /* special_function */
477
         "R_REL",               /* name */
478
         true,                  /* partial_inplace */
479
         0xffff,                /* src_mask */
480
         0xffff,                /* dst_mask */
481
         false),                /* pcrel_offset */
482
 
483
  /* Modifiable branch absolute.  */
484
  HOWTO (0x18,                  /* type */
485
         0,                      /* rightshift */
486
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
487
         16,                    /* bitsize */
488
         false,                 /* pc_relative */
489
         0,                      /* bitpos */
490
         complain_overflow_bitfield, /* complain_on_overflow */
491
         0,                      /* special_function */
492
         "R_RBA",               /* name */
493
         true,                  /* partial_inplace */
494
         0xffff,                /* src_mask */
495
         0xffff,                /* dst_mask */
496
         false),                /* pcrel_offset */
497
 
498
  /* Modifiable branch absolute.  */
499
  HOWTO (0x19,                  /* type */
500
         0,                      /* rightshift */
501
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
502
         16,                    /* bitsize */
503
         false,                 /* pc_relative */
504
         0,                      /* bitpos */
505
         complain_overflow_bitfield, /* complain_on_overflow */
506
         0,                      /* special_function */
507
         "R_RBAC",              /* name */
508
         true,                  /* partial_inplace */
509
         0xffff,                /* src_mask */
510
         0xffff,                /* dst_mask */
511
         false),                /* pcrel_offset */
512
 
513
  /* Modifiable branch relative.  */
514
  HOWTO (0x1a,                  /* type */
515
         0,                      /* rightshift */
516
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
517
         26,                    /* bitsize */
518
         false,                 /* pc_relative */
519
         0,                      /* bitpos */
520
         complain_overflow_signed, /* complain_on_overflow */
521
         0,                      /* special_function */
522
         "R_REL",               /* name */
523
         true,                  /* partial_inplace */
524
         0xffff,                /* src_mask */
525
         0xffff,                /* dst_mask */
526
         false),                /* pcrel_offset */
527
 
528
  /* Modifiable branch absolute.  */
529
  HOWTO (0x1b,                  /* type */
530
         0,                      /* rightshift */
531
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
532
         16,                    /* bitsize */
533
         false,                 /* pc_relative */
534
         0,                      /* bitpos */
535
         complain_overflow_bitfield, /* complain_on_overflow */
536
         0,                      /* special_function */
537
         "R_REL",               /* name */
538
         true,                  /* partial_inplace */
539
         0xffff,                /* src_mask */
540
         0xffff,                /* dst_mask */
541
         false)                 /* pcrel_offset */
542
};
543
 
544
#define HOWTO_COUNT (sizeof nlm_powerpc_howto_table             \
545
                     / sizeof nlm_powerpc_howto_table[0])
546
 
547
/* Read a PowerPC NLM reloc.  */
548
 
549
static boolean
550
nlm_powerpc_read_reloc (abfd, sym, secp, rel)
551
     bfd *abfd;
552
     nlmNAME(symbol_type) *sym;
553
     asection **secp;
554
     arelent *rel;
555
{
556
  struct nlm32_powerpc_external_reloc ext;
557
  bfd_vma l_vaddr;
558
  unsigned long l_symndx;
559
  int l_rtype;
560
  int l_rsecnm;
561
  asection *code_sec, *data_sec, *bss_sec;
562
 
563
  /* Read the reloc from the file.  */
564
  if (bfd_read (&ext, sizeof ext, 1, abfd) != sizeof ext)
565
    return false;
566
 
567
  /* Swap in the fields.  */
568
  l_vaddr = bfd_h_get_32 (abfd, ext.l_vaddr);
569
  l_symndx = bfd_h_get_32 (abfd, ext.l_symndx);
570
  l_rtype = bfd_h_get_16 (abfd, ext.l_rtype);
571
  l_rsecnm = bfd_h_get_16 (abfd, ext.l_rsecnm);
572
 
573
  /* Get the sections now, for convenience.  */
574
  code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
575
  data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
576
  bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
577
 
578
  /* Work out the arelent fields.  */
579
  if (sym != NULL)
580
    {
581
      /* This is an import.  sym_ptr_ptr is filled in by
582
         nlm_canonicalize_reloc.  */
583
      rel->sym_ptr_ptr = NULL;
584
    }
585
  else
586
    {
587
      asection *sec;
588
 
589
      if (l_symndx == 0)
590
        sec = code_sec;
591
      else if (l_symndx == 1)
592
        sec = data_sec;
593
      else if (l_symndx == 2)
594
        sec = bss_sec;
595
      else
596
        {
597
          bfd_set_error (bfd_error_bad_value);
598
          return false;
599
        }
600
 
601
      rel->sym_ptr_ptr = sec->symbol_ptr_ptr;
602
    }
603
 
604
  rel->addend = 0;
605
 
606
  BFD_ASSERT ((l_rtype & 0xff) < HOWTO_COUNT);
607
 
608
  rel->howto = nlm_powerpc_howto_table + (l_rtype & 0xff);
609
 
610
  BFD_ASSERT (rel->howto->name != NULL
611
              && ((l_rtype & 0x8000) != 0
612
                  ? (rel->howto->complain_on_overflow
613
                     == complain_overflow_signed)
614
                  : (rel->howto->complain_on_overflow
615
                     == complain_overflow_bitfield))
616
              && ((l_rtype >> 8) & 0x1f) == rel->howto->bitsize - 1);
617
 
618
  if (l_rsecnm == 0)
619
    *secp = code_sec;
620
  else if (l_rsecnm == 1)
621
    {
622
      *secp = data_sec;
623
      l_vaddr -= bfd_section_size (abfd, code_sec);
624
    }
625
  else
626
    {
627
      bfd_set_error (bfd_error_bad_value);
628
      return false;
629
    }
630
 
631
  rel->address = l_vaddr;
632
 
633
  return true;
634
}
635
 
636
#endif /* OLDFORMAT */
637
 
638
/* Mangle PowerPC NLM relocs for output.  */
639
 
640
static boolean
641
nlm_powerpc_mangle_relocs (abfd, sec, data, offset, count)
642
     bfd *abfd ATTRIBUTE_UNUSED;
643
     asection *sec ATTRIBUTE_UNUSED;
644
     PTR data ATTRIBUTE_UNUSED;
645
     bfd_vma offset ATTRIBUTE_UNUSED;
646
     bfd_size_type count ATTRIBUTE_UNUSED;
647
{
648
  return true;
649
}
650
 
651
/* Read a PowerPC NLM import record */
652
 
653
static boolean
654
nlm_powerpc_read_import (abfd, sym)
655
     bfd *abfd;
656
     nlmNAME(symbol_type) *sym;
657
{
658
  struct nlm_relent *nlm_relocs;        /* relocation records for symbol */
659
  bfd_size_type rcount;                 /* number of relocs */
660
  bfd_byte temp[NLM_TARGET_LONG_SIZE];  /* temporary 32-bit value */
661
  unsigned char symlength;              /* length of symbol name */
662
  char *name;
663
 
664
  if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
665
      != sizeof (symlength))
666
    return (false);
667
  sym -> symbol.the_bfd = abfd;
668
  name = bfd_alloc (abfd, symlength + 1);
669
  if (name == NULL)
670
    return false;
671
  if (bfd_read (name, symlength, 1, abfd) != symlength)
672
    return (false);
673
  name[symlength] = '\0';
674
  sym -> symbol.name = name;
675
  sym -> symbol.flags = 0;
676
  sym -> symbol.value = 0;
677
  sym -> symbol.section = bfd_und_section_ptr;
678
  if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
679
    return (false);
680
  rcount = bfd_h_get_32 (abfd, temp);
681
  nlm_relocs = ((struct nlm_relent *)
682
                bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
683
  if (nlm_relocs == (struct nlm_relent *) NULL)
684
    return false;
685
  sym -> relocs = nlm_relocs;
686
  sym -> rcnt = 0;
687
  while (sym -> rcnt < rcount)
688
    {
689
      asection *section;
690
 
691
      if (nlm_powerpc_read_reloc (abfd, sym, &section,
692
                                  &nlm_relocs -> reloc)
693
          == false)
694
        return false;
695
      nlm_relocs -> section = section;
696
      nlm_relocs++;
697
      sym -> rcnt++;
698
    }
699
  return true;
700
}
701
 
702
#ifndef OLDFORMAT
703
 
704
/* Write a PowerPC NLM reloc.  */
705
 
706
static boolean
707
nlm_powerpc_write_import (abfd, sec, rel)
708
     bfd *abfd;
709
     asection *sec;
710
     arelent *rel;
711
{
712
  asymbol *sym;
713
  bfd_vma val;
714
  bfd_byte temp[4];
715
 
716
  /* PowerPC NetWare only supports one kind of reloc.  */
717
  if (rel->addend != 0
718
      || rel->howto == NULL
719
      || rel->howto->rightshift != 0
720
      || rel->howto->size != 2
721
      || rel->howto->bitsize != 32
722
      || rel->howto->bitpos != 0
723
      || rel->howto->pc_relative
724
      || (rel->howto->src_mask != 0xffffffff && rel->addend != 0)
725
      || rel->howto->dst_mask != 0xffffffff)
726
    {
727
      bfd_set_error (bfd_error_invalid_operation);
728
      return false;
729
    }
730
 
731
  sym = *rel->sym_ptr_ptr;
732
 
733
  /* The value we write out is the offset into the appropriate
734
     segment, rightshifted by two.  This offset is the section vma,
735
     adjusted by the vma of the lowest section in that segment, plus
736
     the address of the relocation.  */
737
  val = bfd_get_section_vma (abfd, sec) + rel->address;
738
  if ((val & 3) != 0)
739
    {
740
      bfd_set_error (bfd_error_bad_value);
741
      return false;
742
    }
743
  val >>= 2;
744
 
745
  /* The high bit is 0 if the reloc is in the data section, or 1 if
746
     the reloc is in the code section.  */
747
  if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
748
    val -= nlm_get_data_low (abfd);
749
  else
750
    {
751
      val -= nlm_get_text_low (abfd);
752
      val |= NLM_HIBIT;
753
    }
754
 
755
  if (! bfd_is_und_section (bfd_get_section (sym)))
756
    {
757
      /* This is an internal relocation fixup.  The second most
758
         significant bit is 0 if this is a reloc against the data
759
         segment, or 1 if it is a reloc against the text segment.  */
760
      if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
761
        val |= NLM_HIBIT >> 1;
762
    }
763
 
764
  bfd_put_32 (abfd, val, temp);
765
  if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
766
    return false;
767
 
768
  return true;
769
}
770
 
771
#else /* OLDFORMAT */
772
 
773
/* This is used for the reloc handling in the old format.  */
774
 
775
/* Write a PowerPC NLM reloc.  */
776
 
777
static boolean
778
nlm_powerpc_write_reloc (abfd, sec, rel, indx)
779
     bfd *abfd;
780
     asection *sec;
781
     arelent *rel;
782
     int indx;
783
{
784
  struct nlm32_powerpc_external_reloc ext;
785
  asection *code_sec, *data_sec, *bss_sec;
786
  asymbol *sym;
787
  asection *symsec;
788
  unsigned long l_symndx;
789
  int l_rtype;
790
  int l_rsecnm;
791
  reloc_howto_type *howto;
792
  bfd_size_type address;
793
 
794
  /* Get the sections now, for convenience.  */
795
  code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
796
  data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
797
  bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
798
 
799
  sym = *rel->sym_ptr_ptr;
800
  symsec = bfd_get_section (sym);
801
  if (indx != -1)
802
    {
803
      BFD_ASSERT (bfd_is_und_section (symsec));
804
      l_symndx = indx + 3;
805
    }
806
  else
807
    {
808
      if (symsec == code_sec)
809
        l_symndx = 0;
810
      else if (symsec == data_sec)
811
        l_symndx = 1;
812
      else if (symsec == bss_sec)
813
        l_symndx = 2;
814
      else
815
        {
816
          bfd_set_error (bfd_error_bad_value);
817
          return false;
818
        }
819
    }
820
 
821
  bfd_h_put_32 (abfd, (bfd_vma) l_symndx, ext.l_symndx);
822
 
823
  for (howto = nlm_powerpc_howto_table;
824
       howto < nlm_powerpc_howto_table + HOWTO_COUNT;
825
       howto++)
826
    {
827
      if (howto->rightshift == rel->howto->rightshift
828
          && howto->size == rel->howto->size
829
          && howto->bitsize == rel->howto->bitsize
830
          && howto->pc_relative == rel->howto->pc_relative
831
          && howto->bitpos == rel->howto->bitpos
832
          && (howto->partial_inplace == rel->howto->partial_inplace
833
              || (! rel->howto->partial_inplace
834
                  && rel->addend == 0))
835
          && (howto->src_mask == rel->howto->src_mask
836
              || (rel->howto->src_mask == 0
837
                  && rel->addend == 0))
838
          && howto->dst_mask == rel->howto->dst_mask
839
          && howto->pcrel_offset == rel->howto->pcrel_offset)
840
        break;
841
    }
842
  if (howto >= nlm_powerpc_howto_table + HOWTO_COUNT)
843
    {
844
      bfd_set_error (bfd_error_bad_value);
845
      return false;
846
    }
847
 
848
  l_rtype = howto->type;
849
  if (howto->complain_on_overflow == complain_overflow_signed)
850
    l_rtype |= 0x8000;
851
  l_rtype |= (howto->bitsize - 1) << 8;
852
  bfd_h_put_16 (abfd, (bfd_vma) l_rtype, ext.l_rtype);
853
 
854
  address = rel->address;
855
 
856
  if (sec == code_sec)
857
    l_rsecnm = 0;
858
  else if (sec == data_sec)
859
    {
860
      l_rsecnm = 1;
861
      address += bfd_section_size (abfd, code_sec);
862
    }
863
  else
864
    {
865
      bfd_set_error (bfd_error_bad_value);
866
      return false;
867
    }
868
 
869
  bfd_h_put_16 (abfd, (bfd_vma) l_rsecnm, ext.l_rsecnm);
870
  bfd_h_put_32 (abfd, (bfd_vma) address, ext.l_vaddr);
871
 
872
  if (bfd_write (&ext, sizeof ext, 1, abfd) != sizeof ext)
873
    return false;
874
 
875
  return true;
876
}
877
 
878
/* Write a PowerPC NLM import.  */
879
 
880
static boolean
881
nlm_powerpc_write_import (abfd, sec, rel)
882
     bfd *abfd;
883
     asection *sec;
884
     arelent *rel;
885
{
886
  return nlm_powerpc_write_reloc (abfd, sec, rel, -1);
887
}
888
 
889
#endif /* OLDFORMAT */
890
 
891
/* Write a PowerPC NLM external symbol.  This routine keeps a static
892
   count of the symbol index.  FIXME: I don't know if this is
893
   necessary, and the index never gets reset.  */
894
 
895
static boolean
896
nlm_powerpc_write_external (abfd, count, sym, relocs)
897
     bfd *abfd;
898
     bfd_size_type count;
899
     asymbol *sym;
900
     struct reloc_and_sec *relocs;
901
{
902
  unsigned int i;
903
  bfd_byte len;
904
  unsigned char temp[NLM_TARGET_LONG_SIZE];
905
#ifdef OLDFORMAT
906
  static int indx;
907
#endif
908
 
909
  len = strlen (sym->name);
910
  if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
911
      || bfd_write (sym->name, len, 1, abfd) != len)
912
    return false;
913
 
914
  bfd_put_32 (abfd, count, temp);
915
  if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
916
    return false;
917
 
918
  for (i = 0; i < count; i++)
919
    {
920
#ifndef OLDFORMAT
921
      if (! nlm_powerpc_write_import (abfd, relocs[i].sec, relocs[i].rel))
922
        return false;
923
#else
924
      if (! nlm_powerpc_write_reloc (abfd, relocs[i].sec,
925
                                     relocs[i].rel, indx))
926
        return false;
927
#endif
928
    }
929
 
930
#ifdef OLDFORMAT
931
  ++indx;
932
#endif
933
 
934
  return true;
935
}
936
 
937
#ifndef OLDFORMAT
938
 
939
/* PowerPC Netware uses a word offset, not a byte offset, for public
940
   symbols.  */
941
 
942
/* Set the section for a public symbol.  */
943
 
944
static boolean
945
nlm_powerpc_set_public_section (abfd, sym)
946
     bfd *abfd;
947
     nlmNAME(symbol_type) *sym;
948
{
949
  if (sym->symbol.value & NLM_HIBIT)
950
    {
951
      sym->symbol.value &= ~NLM_HIBIT;
952
      sym->symbol.flags |= BSF_FUNCTION;
953
      sym->symbol.section =
954
        bfd_get_section_by_name (abfd, NLM_CODE_NAME);
955
    }
956
  else
957
    {
958
      sym->symbol.section =
959
        bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
960
    }
961
 
962
  sym->symbol.value <<= 2;
963
 
964
  return true;
965
}
966
 
967
/* Get the offset to write out for a public symbol.  */
968
 
969
static bfd_vma
970
nlm_powerpc_get_public_offset (abfd, sym)
971
     bfd *abfd;
972
     asymbol *sym;
973
{
974
  bfd_vma offset;
975
  asection *sec;
976
 
977
  offset = bfd_asymbol_value (sym);
978
  sec = bfd_get_section (sym);
979
  if (sec->flags & SEC_CODE)
980
    {
981
      offset -= nlm_get_text_low (abfd);
982
      offset |= NLM_HIBIT;
983
    }
984
  else if (sec->flags & (SEC_DATA | SEC_ALLOC))
985
    {
986
      /* SEC_ALLOC is for the .bss section.  */
987
      offset -= nlm_get_data_low (abfd);
988
    }
989
  else
990
    {
991
      /* We can't handle an exported symbol that is not in the code or
992
         data segment.  */
993
      bfd_set_error (bfd_error_invalid_operation);
994
      /* FIXME: No way to return error.  */
995
      abort ();
996
    }
997
 
998
  return offset;
999
}
1000
 
1001
#endif /* ! defined (OLDFORMAT) */
1002
 
1003
#include "nlmswap.h"
1004
 
1005
static const struct nlm_backend_data nlm32_powerpc_backend =
1006
{
1007
  "NetWare PowerPC Module \032",
1008
  sizeof (Nlm32_powerpc_External_Fixed_Header),
1009
#ifndef OLDFORMAT
1010
  0,     /* optional_prefix_size */
1011
#else
1012
  sizeof (struct nlm32_powerpc_external_prefix_header),
1013
#endif
1014
  bfd_arch_powerpc,
1015
  0,
1016
  false,
1017
#ifndef OLDFORMAT
1018
  0,     /* backend_object_p */
1019
  0,     /* write_prefix */
1020
#else
1021
  nlm_powerpc_backend_object_p,
1022
  nlm_powerpc_write_prefix,
1023
#endif
1024
  nlm_powerpc_read_reloc,
1025
  nlm_powerpc_mangle_relocs,
1026
  nlm_powerpc_read_import,
1027
  nlm_powerpc_write_import,
1028
#ifndef OLDFORMAT
1029
  nlm_powerpc_set_public_section,
1030
  nlm_powerpc_get_public_offset,
1031
#else
1032
  0,     /* set_public_section */
1033
  0,     /* get_public_offset */
1034
#endif
1035
  nlm_swap_fixed_header_in,
1036
  nlm_swap_fixed_header_out,
1037
  nlm_powerpc_write_external,
1038
  0,     /* write_export */
1039
};
1040
 
1041
#define TARGET_BIG_NAME                 "nlm32-powerpc"
1042
#define TARGET_BIG_SYM                  nlmNAME(powerpc_vec)
1043
#define TARGET_BACKEND_DATA             &nlm32_powerpc_backend
1044
 
1045
#include "nlm-target.h"

powered by: WebSVN 2.1.0

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