~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to binutils/bfd/nlm32-sparc.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Support for 32-bit SPARC NLM (NetWare Loadable Module)
 
2
   Copyright 1993, 1994, 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
#define ARCH_SIZE 32
 
25
 
 
26
#include "nlm/sparc32-ext.h"
 
27
#define Nlm_External_Fixed_Header       Nlm32_sparc_External_Fixed_Header
 
28
 
 
29
#include "libnlm.h"
 
30
 
 
31
static boolean nlm_sparc_read_reloc
 
32
  PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
 
33
static boolean nlm_sparc_write_reloc
 
34
  PARAMS ((bfd *, asection *, arelent *));
 
35
static boolean nlm_sparc_mangle_relocs
 
36
  PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
 
37
static boolean nlm_sparc_read_import
 
38
  PARAMS ((bfd *, nlmNAME(symbol_type) *));
 
39
static boolean nlm_sparc_write_import
 
40
  PARAMS ((bfd *, asection *, arelent *));
 
41
static boolean nlm_sparc_write_external
 
42
  PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
 
43
static boolean nlm_sparc_write_export
 
44
  PARAMS ((bfd *, asymbol *, bfd_vma));
 
45
 
 
46
enum reloc_type
 
47
  {
 
48
    R_SPARC_NONE = 0,
 
49
    R_SPARC_8,          R_SPARC_16,             R_SPARC_32,
 
50
    R_SPARC_DISP8,      R_SPARC_DISP16,         R_SPARC_DISP32,
 
51
    R_SPARC_WDISP30,    R_SPARC_WDISP22,
 
52
    R_SPARC_HI22,       R_SPARC_22,
 
53
    R_SPARC_13,         R_SPARC_LO10,
 
54
    R_SPARC_GOT10,      R_SPARC_GOT13,          R_SPARC_GOT22,
 
55
    R_SPARC_PC10,       R_SPARC_PC22,
 
56
    R_SPARC_WPLT30,
 
57
    R_SPARC_COPY,
 
58
    R_SPARC_GLOB_DAT,   R_SPARC_JMP_SLOT,
 
59
    R_SPARC_RELATIVE,
 
60
    R_SPARC_UA32,
 
61
    R_SPARC_max
 
62
  };
 
63
 
 
64
#if 0
 
65
static const char *const reloc_type_names[] =
 
66
  {
 
67
    "R_SPARC_NONE",
 
68
    "R_SPARC_8",                "R_SPARC_16",           "R_SPARC_32",
 
69
    "R_SPARC_DISP8",    "R_SPARC_DISP16",       "R_SPARC_DISP32",
 
70
    "R_SPARC_WDISP30",  "R_SPARC_WDISP22",
 
71
    "R_SPARC_HI22",     "R_SPARC_22",
 
72
    "R_SPARC_13",               "R_SPARC_LO10",
 
73
    "R_SPARC_GOT10",    "R_SPARC_GOT13",        "R_SPARC_GOT22",
 
74
    "R_SPARC_PC10",     "R_SPARC_PC22",
 
75
    "R_SPARC_WPLT30",
 
76
    "R_SPARC_COPY",
 
77
    "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT",
 
78
    "R_SPARC_RELATIVE",
 
79
    "R_SPARC_UA32",
 
80
  };
 
81
#endif
 
82
 
 
83
static reloc_howto_type nlm32_sparc_howto_table[] =
 
84
  {
 
85
    HOWTO (R_SPARC_NONE,    0,0, 0,false,0,complain_overflow_dont,    0,"R_SPARC_NONE",    false,0,0x00000000,true),
 
86
    HOWTO (R_SPARC_8,       0,0, 8,false,0,complain_overflow_bitfield,0,"R_SPARC_8",       false,0,0x000000ff,true),
 
87
    HOWTO (R_SPARC_16,      0,1,16,false,0,complain_overflow_bitfield,0,"R_SPARC_16",      false,0,0x0000ffff,true),
 
88
    HOWTO (R_SPARC_32,      0,2,32,false,0,complain_overflow_bitfield,0,"R_SPARC_32",      false,0,0xffffffff,true),
 
89
    HOWTO (R_SPARC_DISP8,   0,0, 8,true, 0,complain_overflow_signed,  0,"R_SPARC_DISP8",   false,0,0x000000ff,true),
 
90
    HOWTO (R_SPARC_DISP16,  0,1,16,true, 0,complain_overflow_signed,  0,"R_SPARC_DISP16",  false,0,0x0000ffff,true),
 
91
    HOWTO (R_SPARC_DISP32,  0,2,32,true, 0,complain_overflow_signed,  0,"R_SPARC_DISP32",  false,0,0x00ffffff,true),
 
92
    HOWTO (R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed,  0,"R_SPARC_WDISP30", false,0,0x3fffffff,true),
 
93
    HOWTO (R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed,  0,"R_SPARC_WDISP22", false,0,0x003fffff,true),
 
94
    HOWTO (R_SPARC_HI22,   10,2,22,false,0,complain_overflow_dont,    0,"R_SPARC_HI22",    false,0,0x003fffff,true),
 
95
    HOWTO (R_SPARC_22,      0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_22",      false,0,0x003fffff,true),
 
96
    HOWTO (R_SPARC_13,      0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_13",      false,0,0x00001fff,true),
 
97
    HOWTO (R_SPARC_LO10,    0,2,10,false,0,complain_overflow_dont,    0,"R_SPARC_LO10",    false,0,0x000003ff,true),
 
98
    HOWTO (R_SPARC_GOT10,   0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT10",   false,0,0x000003ff,true),
 
99
    HOWTO (R_SPARC_GOT13,   0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT13",   false,0,0x00001fff,true),
 
100
    HOWTO (R_SPARC_GOT22,  10,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT22",   false,0,0x003fffff,true),
 
101
    HOWTO (R_SPARC_PC10,    0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_PC10",    false,0,0x000003ff,true),
 
102
    HOWTO (R_SPARC_PC22,    0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_PC22",    false,0,0x003fffff,true),
 
103
    HOWTO (R_SPARC_WPLT30,  0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_WPLT30",  false,0,0x00000000,true),
 
104
    HOWTO (R_SPARC_COPY,    0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_COPY",    false,0,0x00000000,true),
 
105
    HOWTO (R_SPARC_GLOB_DAT,0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_GLOB_DAT",false,0,0x00000000,true),
 
106
    HOWTO (R_SPARC_JMP_SLOT,0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_JMP_SLOT",false,0,0x00000000,true),
 
107
    HOWTO (R_SPARC_RELATIVE,0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_RELATIVE",false,0,0x00000000,true),
 
108
    HOWTO (R_SPARC_UA32,    0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_UA32",    false,0,0x00000000,true),
 
109
};
 
110
 
 
111
/* Read a NetWare sparc reloc.  */
 
112
 
 
113
struct nlm32_sparc_reloc_ext
 
114
  {
 
115
    unsigned char offset[4];
 
116
    unsigned char addend[4];
 
117
    unsigned char type[1];
 
118
    unsigned char pad1[3];
 
119
  };
 
120
 
 
121
static boolean
 
122
nlm_sparc_read_reloc (abfd, sym, secp, rel)
 
123
     bfd *abfd;
 
124
     nlmNAME(symbol_type) *sym ATTRIBUTE_UNUSED;
 
125
     asection **secp;
 
126
     arelent *rel;
 
127
{
 
128
  bfd_vma val, addend;
 
129
  unsigned int index;
 
130
  unsigned int type;
 
131
  struct nlm32_sparc_reloc_ext tmp_reloc;
 
132
  asection *code_sec, *data_sec;
 
133
 
 
134
  if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
 
135
    return false;
 
136
 
 
137
  code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
 
138
  data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
 
139
 
 
140
  *secp = code_sec;
 
141
 
 
142
  val = bfd_get_32 (abfd, tmp_reloc.offset);
 
143
  addend = bfd_get_32 (abfd, tmp_reloc.addend);
 
144
  type = bfd_get_8 (abfd, tmp_reloc.type);
 
145
 
 
146
  rel->address = val;
 
147
  rel->addend = addend;
 
148
  rel->howto = NULL;
 
149
 
 
150
  for (index = 0;
 
151
       index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
 
152
       index++)
 
153
    if (nlm32_sparc_howto_table[index].type == type)
 
154
      {
 
155
        rel->howto = &nlm32_sparc_howto_table[index];
 
156
        break;
 
157
      }
 
158
 
 
159
#ifdef DEBUG
 
160
  fprintf (stderr, "%s:  address = %08lx, addend = %08lx, type = %d, howto = %08lx\n",
 
161
           __FUNCTION__, rel->address, rel->addend, type, rel->howto);
 
162
#endif
 
163
  return true;
 
164
 
 
165
}
 
166
 
 
167
/* Write a NetWare sparc reloc.  */
 
168
 
 
169
static boolean
 
170
nlm_sparc_write_reloc (abfd, sec, rel)
 
171
     bfd *abfd;
 
172
     asection *sec;
 
173
     arelent *rel;
 
174
{
 
175
  bfd_vma val;
 
176
  struct nlm32_sparc_reloc_ext tmp_reloc;
 
177
  unsigned int index;
 
178
  int type = -1;
 
179
  reloc_howto_type *tmp;
 
180
 
 
181
  for (index = 0;
 
182
       index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
 
183
       index++)
 
184
    {
 
185
      tmp = &nlm32_sparc_howto_table[index];
 
186
 
 
187
      if (tmp->rightshift == rel->howto->rightshift
 
188
          && tmp->size == rel->howto->size
 
189
          && tmp->bitsize == rel->howto->bitsize
 
190
          && tmp->pc_relative == rel->howto->pc_relative
 
191
          && tmp->bitpos == rel->howto->bitpos
 
192
          && tmp->src_mask == rel->howto->src_mask
 
193
          && tmp->dst_mask == rel->howto->dst_mask)
 
194
        {
 
195
          type = tmp->type;
 
196
          break;
 
197
        }
 
198
    }
 
199
  if (type == -1)
 
200
    abort ();
 
201
 
 
202
  /* Netware wants a list of relocs for each address.
 
203
     Format is:
 
204
        long    offset
 
205
        long    addend
 
206
        char    type
 
207
     That should be it.  */
 
208
 
 
209
  /* The value we write out is the offset into the appropriate
 
210
     segment.  This offset is the section vma, adjusted by the vma of
 
211
     the lowest section in that segment, plus the address of the
 
212
     relocation.  */
 
213
#if 0
 
214
  val = bfd_get_section_vma (abfd, (*rel->sym_ptr_ptr)->section) + rel->address;
 
215
#else
 
216
  val = bfd_get_section_vma (abfd, sec) + rel->address;
 
217
#endif
 
218
 
 
219
#ifdef DEBUG
 
220
  fprintf (stderr, "%s:  val = %08lx, addend = %08lx, type = %d\n",
 
221
           __FUNCTION__, val, rel->addend, rel->howto->type);
 
222
#endif
 
223
  bfd_put_32 (abfd, val, tmp_reloc.offset);
 
224
  bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
 
225
  bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
 
226
 
 
227
  if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
 
228
    return false;
 
229
 
 
230
  return true;
 
231
}
 
232
 
 
233
/* Mangle relocs for SPARC NetWare.  We can just use the standard
 
234
   SPARC relocs.  */
 
235
 
 
236
static boolean
 
237
nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
 
238
     bfd *abfd ATTRIBUTE_UNUSED;
 
239
     asection *sec ATTRIBUTE_UNUSED;
 
240
     PTR data ATTRIBUTE_UNUSED;
 
241
     bfd_vma offset ATTRIBUTE_UNUSED;
 
242
     bfd_size_type count ATTRIBUTE_UNUSED;
 
243
{
 
244
  return true;
 
245
}
 
246
 
 
247
/* Read a NetWare sparc import record.  */
 
248
 
 
249
static boolean
 
250
nlm_sparc_read_import (abfd, sym)
 
251
     bfd *abfd;
 
252
     nlmNAME(symbol_type) *sym;
 
253
{
 
254
  struct nlm_relent *nlm_relocs;        /* Relocation records for symbol.  */
 
255
  bfd_size_type rcount;                 /* Number of relocs.  */
 
256
  bfd_byte temp[NLM_TARGET_LONG_SIZE];  /* Temporary 32-bit value.  */
 
257
  unsigned char symlength;              /* Length of symbol name.  */
 
258
  char *name;
 
259
 
 
260
  /* First, read in the number of relocation
 
261
     entries for this symbol.  */
 
262
  if (bfd_bread ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
 
263
    return false;
 
264
 
 
265
  rcount = bfd_get_32 (abfd, temp);
 
266
 
 
267
  /* Next, read in the length of the symbol.  */
 
268
 
 
269
  if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd)
 
270
      != sizeof (symlength))
 
271
    return false;
 
272
  sym -> symbol.the_bfd = abfd;
 
273
  name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
 
274
  if (name == NULL)
 
275
    return false;
 
276
 
 
277
  /* Then read in the symbol.  */
 
278
 
 
279
  if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
 
280
    return false;
 
281
  name[symlength] = '\0';
 
282
  sym -> symbol.name = name;
 
283
  sym -> symbol.flags = 0;
 
284
  sym -> symbol.value = 0;
 
285
  sym -> symbol.section = bfd_und_section_ptr;
 
286
 
 
287
  /* Next, start reading in the relocs.  */
 
288
 
 
289
  nlm_relocs = ((struct nlm_relent *)
 
290
                bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
 
291
  if (!nlm_relocs)
 
292
    return false;
 
293
  sym -> relocs = nlm_relocs;
 
294
  sym -> rcnt = 0;
 
295
  while (sym -> rcnt < rcount)
 
296
    {
 
297
      asection *section;
 
298
 
 
299
      if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
 
300
        return false;
 
301
      nlm_relocs -> section = section;
 
302
      nlm_relocs++;
 
303
      sym -> rcnt++;
 
304
    }
 
305
 
 
306
  return true;
 
307
}
 
308
 
 
309
static boolean
 
310
nlm_sparc_write_import (abfd, sec, rel)
 
311
     bfd *abfd;
 
312
     asection *sec;
 
313
     arelent *rel;
 
314
{
 
315
  char temp[4];
 
316
  asection *code, *data, *bss, *symsec;
 
317
  bfd_vma base;
 
318
 
 
319
  code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
 
320
  data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
 
321
  bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
 
322
  symsec = (*rel->sym_ptr_ptr)->section;
 
323
 
 
324
  if (symsec == code)
 
325
    base = 0;
 
326
  else if (symsec == data)
 
327
    base = bfd_section_size (abfd, code);
 
328
  else if (symsec == bss)
 
329
    base = bfd_section_size (abfd, code) + bfd_section_size (abfd, data);
 
330
  else
 
331
    base = 0;
 
332
 
 
333
#ifdef DEBUG
 
334
  fprintf (stderr, "%s:  <%x, 1>\n\t",
 
335
           __FUNCTION__, base + (*rel->sym_ptr_ptr)->value);
 
336
#endif
 
337
  bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
 
338
  if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
 
339
    return false;
 
340
  bfd_put_32 (abfd, (bfd_vma) 1, temp);
 
341
  if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
 
342
    return false;
 
343
  if (! nlm_sparc_write_reloc (abfd, sec, rel))
 
344
    return false;
 
345
  return true;
 
346
}
 
347
 
 
348
/* Write out an external reference.  */
 
349
 
 
350
static boolean
 
351
nlm_sparc_write_external (abfd, count, sym, relocs)
 
352
     bfd *abfd;
 
353
     bfd_size_type count;
 
354
     asymbol *sym;
 
355
     struct reloc_and_sec *relocs;
 
356
{
 
357
  unsigned int i;
 
358
  bfd_byte len;
 
359
  unsigned char temp[NLM_TARGET_LONG_SIZE];
 
360
 
 
361
  bfd_put_32 (abfd, count, temp);
 
362
  if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
 
363
    return false;
 
364
 
 
365
  len = strlen (sym->name);
 
366
  if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
 
367
       != sizeof (bfd_byte))
 
368
      || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
 
369
    return false;
 
370
 
 
371
  for (i = 0; i < count; i++)
 
372
    {
 
373
      if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
 
374
        return false;
 
375
    }
 
376
 
 
377
  return true;
 
378
}
 
379
 
 
380
static boolean
 
381
nlm_sparc_write_export (abfd, sym, value)
 
382
     bfd *abfd;
 
383
     asymbol *sym;
 
384
     bfd_vma value;
 
385
{
 
386
  bfd_byte len;
 
387
  bfd_byte temp[4];
 
388
 
 
389
#ifdef DEBUG
 
390
  fprintf (stderr, "%s: <%x, %d, %s>\n",
 
391
           __FUNCTION__, value, strlen (sym->name), sym->name);
 
392
#endif
 
393
  bfd_put_32 (abfd, value, temp);
 
394
  len = strlen (sym->name);
 
395
 
 
396
  if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4
 
397
      || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1
 
398
      || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
 
399
    return false;
 
400
 
 
401
  return true;
 
402
}
 
403
 
 
404
#undef nlm_swap_fixed_header_in
 
405
#undef nlm_swap_fixed_header_out
 
406
 
 
407
#include "nlmswap.h"
 
408
 
 
409
static const struct nlm_backend_data nlm32_sparc_backend =
 
410
  {
 
411
    "NetWare SPARC Module   \032",
 
412
    sizeof (Nlm32_sparc_External_Fixed_Header),
 
413
    0,  /* optional_prefix_size */
 
414
    bfd_arch_sparc,
 
415
    0,
 
416
    false,
 
417
    0,  /* backend_object_p */
 
418
    0,  /* write_prefix_func */
 
419
    nlm_sparc_read_reloc,
 
420
    nlm_sparc_mangle_relocs,
 
421
    nlm_sparc_read_import,
 
422
    nlm_sparc_write_import,
 
423
    0,  /* set_public_section */
 
424
    0,  /* get_public_offset */
 
425
    nlm_swap_fixed_header_in,
 
426
    nlm_swap_fixed_header_out,
 
427
    nlm_sparc_write_external,
 
428
    nlm_sparc_write_export
 
429
  };
 
430
 
 
431
#define TARGET_BIG_NAME         "nlm32-sparc"
 
432
#define TARGET_BIG_SYM          nlmNAME(sparc_vec)
 
433
#define TARGET_BACKEND_DATA     & nlm32_sparc_backend
 
434
 
 
435
#include "nlm-target.h"