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

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [bfd/] [nlm32-ppc.c] - Blame information for rev 1181

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

Line No. Rev Author Line
1 1181 sfurman
/* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
2
   Copyright 1994, 1995, 2000, 2001, 2002 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_bread ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s)
80
    return false;
81
 
82
  if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0
83
      || 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
  H_PUT_32 (abfd, NLM32_POWERPC_HEADER_VERSION, s.headerVersion);
100
  H_PUT_32 (abfd, 0, s.origins);
101
 
102
  /* FIXME: What should we do about the date?  */
103
 
104
  if (bfd_bwrite ((PTR) &s, (bfd_size_type) sizeof s, 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_bread (temp, (bfd_size_type) sizeof (temp), 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_bread (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
565
    return false;
566
 
567
  /* Swap in the fields.  */
568
  l_vaddr = H_GET_32 (abfd, ext.l_vaddr);
569
  l_symndx = H_GET_32 (abfd, ext.l_symndx);
570
  l_rtype = H_GET_16 (abfd, ext.l_rtype);
571
  l_rsecnm = 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_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd)
665
      != sizeof (symlength))
666
    return (false);
667
  sym -> symbol.the_bfd = abfd;
668
  name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
669
  if (name == NULL)
670
    return false;
671
  if (bfd_bread (name, (bfd_size_type) symlength, 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_bread ((PTR) temp, (bfd_size_type) sizeof (temp), abfd)
679
      != sizeof (temp))
680
    return (false);
681
  rcount = H_GET_32 (abfd, temp);
682
  nlm_relocs = ((struct nlm_relent *)
683
                bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
684
  if (nlm_relocs == (struct nlm_relent *) NULL)
685
    return false;
686
  sym -> relocs = nlm_relocs;
687
  sym -> rcnt = 0;
688
  while (sym -> rcnt < rcount)
689
    {
690
      asection *section;
691
 
692
      if (! nlm_powerpc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
693
        return false;
694
      nlm_relocs -> section = section;
695
      nlm_relocs++;
696
      sym -> rcnt++;
697
    }
698
  return true;
699
}
700
 
701
#ifndef OLDFORMAT
702
 
703
/* Write a PowerPC NLM reloc.  */
704
 
705
static boolean
706
nlm_powerpc_write_import (abfd, sec, rel)
707
     bfd *abfd;
708
     asection *sec;
709
     arelent *rel;
710
{
711
  asymbol *sym;
712
  bfd_vma val;
713
  bfd_byte temp[4];
714
 
715
  /* PowerPC NetWare only supports one kind of reloc.  */
716
  if (rel->addend != 0
717
      || rel->howto == NULL
718
      || rel->howto->rightshift != 0
719
      || rel->howto->size != 2
720
      || rel->howto->bitsize != 32
721
      || rel->howto->bitpos != 0
722
      || rel->howto->pc_relative
723
      || (rel->howto->src_mask != 0xffffffff && rel->addend != 0)
724
      || rel->howto->dst_mask != 0xffffffff)
725
    {
726
      bfd_set_error (bfd_error_invalid_operation);
727
      return false;
728
    }
729
 
730
  sym = *rel->sym_ptr_ptr;
731
 
732
  /* The value we write out is the offset into the appropriate
733
     segment, rightshifted by two.  This offset is the section vma,
734
     adjusted by the vma of the lowest section in that segment, plus
735
     the address of the relocation.  */
736
  val = bfd_get_section_vma (abfd, sec) + rel->address;
737
  if ((val & 3) != 0)
738
    {
739
      bfd_set_error (bfd_error_bad_value);
740
      return false;
741
    }
742
  val >>= 2;
743
 
744
  /* The high bit is 0 if the reloc is in the data section, or 1 if
745
     the reloc is in the code section.  */
746
  if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
747
    val -= nlm_get_data_low (abfd);
748
  else
749
    {
750
      val -= nlm_get_text_low (abfd);
751
      val |= NLM_HIBIT;
752
    }
753
 
754
  if (! bfd_is_und_section (bfd_get_section (sym)))
755
    {
756
      /* This is an internal relocation fixup.  The second most
757
         significant bit is 0 if this is a reloc against the data
758
         segment, or 1 if it is a reloc against the text segment.  */
759
      if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
760
        val |= NLM_HIBIT >> 1;
761
    }
762
 
763
  bfd_put_32 (abfd, val, temp);
764
  if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
765
    return false;
766
 
767
  return true;
768
}
769
 
770
#else /* OLDFORMAT */
771
 
772
/* This is used for the reloc handling in the old format.  */
773
 
774
/* Write a PowerPC NLM reloc.  */
775
 
776
static boolean
777
nlm_powerpc_write_reloc (abfd, sec, rel, indx)
778
     bfd *abfd;
779
     asection *sec;
780
     arelent *rel;
781
     int indx;
782
{
783
  struct nlm32_powerpc_external_reloc ext;
784
  asection *code_sec, *data_sec, *bss_sec;
785
  asymbol *sym;
786
  asection *symsec;
787
  unsigned long l_symndx;
788
  int l_rtype;
789
  int l_rsecnm;
790
  reloc_howto_type *howto;
791
  bfd_size_type address;
792
 
793
  /* Get the sections now, for convenience.  */
794
  code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
795
  data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
796
  bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
797
 
798
  sym = *rel->sym_ptr_ptr;
799
  symsec = bfd_get_section (sym);
800
  if (indx != -1)
801
    {
802
      BFD_ASSERT (bfd_is_und_section (symsec));
803
      l_symndx = indx + 3;
804
    }
805
  else
806
    {
807
      if (symsec == code_sec)
808
        l_symndx = 0;
809
      else if (symsec == data_sec)
810
        l_symndx = 1;
811
      else if (symsec == bss_sec)
812
        l_symndx = 2;
813
      else
814
        {
815
          bfd_set_error (bfd_error_bad_value);
816
          return false;
817
        }
818
    }
819
 
820
  H_PUT_32 (abfd, l_symndx, ext.l_symndx);
821
 
822
  for (howto = nlm_powerpc_howto_table;
823
       howto < nlm_powerpc_howto_table + HOWTO_COUNT;
824
       howto++)
825
    {
826
      if (howto->rightshift == rel->howto->rightshift
827
          && howto->size == rel->howto->size
828
          && howto->bitsize == rel->howto->bitsize
829
          && howto->pc_relative == rel->howto->pc_relative
830
          && howto->bitpos == rel->howto->bitpos
831
          && (howto->partial_inplace == rel->howto->partial_inplace
832
              || (! rel->howto->partial_inplace
833
                  && rel->addend == 0))
834
          && (howto->src_mask == rel->howto->src_mask
835
              || (rel->howto->src_mask == 0
836
                  && rel->addend == 0))
837
          && howto->dst_mask == rel->howto->dst_mask
838
          && howto->pcrel_offset == rel->howto->pcrel_offset)
839
        break;
840
    }
841
  if (howto >= nlm_powerpc_howto_table + HOWTO_COUNT)
842
    {
843
      bfd_set_error (bfd_error_bad_value);
844
      return false;
845
    }
846
 
847
  l_rtype = howto->type;
848
  if (howto->complain_on_overflow == complain_overflow_signed)
849
    l_rtype |= 0x8000;
850
  l_rtype |= (howto->bitsize - 1) << 8;
851
  H_PUT_16 (abfd, l_rtype, ext.l_rtype);
852
 
853
  address = rel->address;
854
 
855
  if (sec == code_sec)
856
    l_rsecnm = 0;
857
  else if (sec == data_sec)
858
    {
859
      l_rsecnm = 1;
860
      address += bfd_section_size (abfd, code_sec);
861
    }
862
  else
863
    {
864
      bfd_set_error (bfd_error_bad_value);
865
      return false;
866
    }
867
 
868
  H_PUT_16 (abfd, l_rsecnm, ext.l_rsecnm);
869
  H_PUT_32 (abfd, address, ext.l_vaddr);
870
 
871
  if (bfd_bwrite (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
872
    return false;
873
 
874
  return true;
875
}
876
 
877
/* Write a PowerPC NLM import.  */
878
 
879
static boolean
880
nlm_powerpc_write_import (abfd, sec, rel)
881
     bfd *abfd;
882
     asection *sec;
883
     arelent *rel;
884
{
885
  return nlm_powerpc_write_reloc (abfd, sec, rel, -1);
886
}
887
 
888
#endif /* OLDFORMAT */
889
 
890
/* Write a PowerPC NLM external symbol.  This routine keeps a static
891
   count of the symbol index.  FIXME: I don't know if this is
892
   necessary, and the index never gets reset.  */
893
 
894
static boolean
895
nlm_powerpc_write_external (abfd, count, sym, relocs)
896
     bfd *abfd;
897
     bfd_size_type count;
898
     asymbol *sym;
899
     struct reloc_and_sec *relocs;
900
{
901
  unsigned int i;
902
  bfd_byte len;
903
  unsigned char temp[NLM_TARGET_LONG_SIZE];
904
#ifdef OLDFORMAT
905
  static int indx;
906
#endif
907
 
908
  len = strlen (sym->name);
909
  if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
910
       != sizeof (bfd_byte))
911
      || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
912
    return false;
913
 
914
  bfd_put_32 (abfd, count, temp);
915
  if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), 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.