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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [bfd/] [nlm32-ppc.c] - Blame information for rev 843

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

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

powered by: WebSVN 2.1.0

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