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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [bfd/] [elf32-avr.c] - Blame information for rev 1771

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

Line No. Rev Author Line
1 104 markom
/* AVR-specific support for 32-bit ELF
2
   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
3
   Contributed by Denis Chertykov <denisc@overta.ru>
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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
 
22
#include "bfd.h"
23
#include "sysdep.h"
24
#include "libbfd.h"
25
#include "elf-bfd.h"
26
#include "elf/avr.h"
27
 
28
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
29
  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
30
static void avr_info_to_howto_rela
31
  PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
32
static asection *elf32_avr_gc_mark_hook
33
  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
34
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
35
static boolean elf32_avr_gc_sweep_hook
36
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
37
           const Elf_Internal_Rela *));
38
static boolean elf32_avr_check_relocs
39
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
40
           const Elf_Internal_Rela *));
41
static bfd_reloc_status_type avr_final_link_relocate
42
  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
43
           Elf_Internal_Rela *, bfd_vma));
44
static boolean elf32_avr_relocate_section
45
  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
46
           Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
47
static void bfd_elf_avr_final_write_processing PARAMS ((bfd *, boolean));
48
static boolean elf32_avr_object_p PARAMS ((bfd *));
49
 
50
 
51
/* Use RELA instead of REL */
52
#undef USE_REL
53
 
54
static reloc_howto_type elf_avr_howto_table[] =
55
{
56
  HOWTO (R_AVR_NONE,            /* type */
57
         0,                      /* rightshift */
58
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
59
         32,                    /* bitsize */
60
         false,                 /* pc_relative */
61
         0,                      /* bitpos */
62
         complain_overflow_bitfield, /* complain_on_overflow */
63
         bfd_elf_generic_reloc, /* special_function */
64
         "R_AVR_NONE",          /* name */
65
         false,                 /* partial_inplace */
66
         0,                      /* src_mask */
67
         0,                      /* dst_mask */
68
         false),                /* pcrel_offset */
69
 
70
  HOWTO (R_AVR_32,              /* type */
71
         0,                      /* rightshift */
72
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
73
         32,                    /* bitsize */
74
         false,                 /* pc_relative */
75
         0,                      /* bitpos */
76
         complain_overflow_bitfield, /* complain_on_overflow */
77
         bfd_elf_generic_reloc, /* special_function */
78
         "R_AVR_32",            /* name */
79
         false,                 /* partial_inplace */
80
         0xffffffff,            /* src_mask */
81
         0xffffffff,            /* dst_mask */
82
         false),                /* pcrel_offset */
83
 
84
  /* A 7 bit PC relative relocation.  */
85
  HOWTO (R_AVR_7_PCREL,         /* type */
86
         1,                     /* rightshift */
87
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
88
         7,                     /* bitsize */
89
         true,                  /* pc_relative */
90
         3,                     /* bitpos */
91
         complain_overflow_bitfield, /* complain_on_overflow */
92
         bfd_elf_generic_reloc, /* special_function */
93
         "R_AVR_7_PCREL",       /* name */
94
         false,                 /* partial_inplace */
95
         0xffff,                /* src_mask */
96
         0xffff,                /* dst_mask */
97
         true),                 /* pcrel_offset */
98
 
99
  /* A 13 bit PC relative relocation.  */
100
  HOWTO (R_AVR_13_PCREL,        /* type */
101
         1,                     /* rightshift */
102
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
103
         13,                    /* bitsize */
104
         true,                  /* pc_relative */
105
         0,                      /* bitpos */
106
         complain_overflow_bitfield, /* complain_on_overflow */
107
         bfd_elf_generic_reloc, /* special_function */
108
         "R_AVR_13_PCREL",      /* name */
109
         false,                 /* partial_inplace */
110
         0xfff,                 /* src_mask */
111
         0xfff,                 /* dst_mask */
112
         true),                 /* pcrel_offset */
113
 
114
  /* A 16 bit absolute relocation.  */
115
  HOWTO (R_AVR_16,              /* type */
116
         0,                      /* rightshift */
117
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
118
         16,                    /* bitsize */
119
         false,                 /* pc_relative */
120
         0,                      /* bitpos */
121
         complain_overflow_dont, /* complain_on_overflow */
122
         bfd_elf_generic_reloc, /* special_function */
123
         "R_AVR_16",            /* name */
124
         false,                 /* partial_inplace */
125
         0xffff,                /* src_mask */
126
         0xffff,                /* dst_mask */
127
         false),                /* pcrel_offset */
128
 
129
  /* A 16 bit absolute relocation for command address.  */
130
  HOWTO (R_AVR_16_PM,           /* type */
131
         1,                     /* rightshift */
132
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
133
         16,                    /* bitsize */
134
         false,                 /* pc_relative */
135
         0,                      /* bitpos */
136
         complain_overflow_bitfield, /* complain_on_overflow */
137
         bfd_elf_generic_reloc, /* special_function */
138
         "R_AVR_16_PM",         /* name */
139
         false,                 /* partial_inplace */
140
         0xffff,                /* src_mask */
141
         0xffff,                /* dst_mask */
142
         false),                /* pcrel_offset */
143
  /* A low 8 bit absolute relocation of 16 bit address.
144
     For LDI command.  */
145
  HOWTO (R_AVR_LO8_LDI,         /* type */
146
         0,                      /* rightshift */
147
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
148
         8,                     /* bitsize */
149
         false,                 /* pc_relative */
150
         0,                      /* bitpos */
151
         complain_overflow_dont, /* complain_on_overflow */
152
         bfd_elf_generic_reloc, /* special_function */
153
         "R_AVR_LO8_LDI",       /* name */
154
         false,                 /* partial_inplace */
155
         0xffff,                /* src_mask */
156
         0xffff,                /* dst_mask */
157
         false),                /* pcrel_offset */
158
  /* A high 8 bit absolute relocation of 16 bit address.
159
     For LDI command.  */
160
  HOWTO (R_AVR_HI8_LDI,         /* type */
161
         8,                     /* rightshift */
162
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
163
         8,                     /* bitsize */
164
         false,                 /* pc_relative */
165
         0,                      /* bitpos */
166
         complain_overflow_dont, /* complain_on_overflow */
167
         bfd_elf_generic_reloc, /* special_function */
168
         "R_AVR_HI8_LDI",       /* name */
169
         false,                 /* partial_inplace */
170
         0xffff,                /* src_mask */
171
         0xffff,                /* dst_mask */
172
         false),                /* pcrel_offset */
173
  /* A high 6 bit absolute relocation of 22 bit address.
174
     For LDI command.  */
175
  HOWTO (R_AVR_HH8_LDI,         /* type */
176
         16,                    /* rightshift */
177
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
178
         8,                     /* bitsize */
179
         false,                 /* pc_relative */
180
         0,                      /* bitpos */
181
         complain_overflow_dont, /* complain_on_overflow */
182
         bfd_elf_generic_reloc, /* special_function */
183
         "R_AVR_HH8_LDI",       /* name */
184
         false,                 /* partial_inplace */
185
         0xffff,                /* src_mask */
186
         0xffff,                /* dst_mask */
187
         false),                /* pcrel_offset */
188
  /* A negative low 8 bit absolute relocation of 16 bit address.
189
     For LDI command.  */
190
  HOWTO (R_AVR_LO8_LDI_NEG,     /* type */
191
         0,                      /* rightshift */
192
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
193
         8,                     /* bitsize */
194
         false,                 /* pc_relative */
195
         0,                      /* bitpos */
196
         complain_overflow_dont, /* complain_on_overflow */
197
         bfd_elf_generic_reloc, /* special_function */
198
         "R_AVR_LO8_LDI_NEG",   /* name */
199
         false,                 /* partial_inplace */
200
         0xffff,                /* src_mask */
201
         0xffff,                /* dst_mask */
202
         false),                /* pcrel_offset */
203
  /* A hegative high 8 bit absolute relocation of 16 bit address.
204
     For LDI command.  */
205
  HOWTO (R_AVR_HI8_LDI_NEG,     /* type */
206
         8,                     /* rightshift */
207
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
208
         8,                     /* bitsize */
209
         false,                 /* pc_relative */
210
         0,                      /* bitpos */
211
         complain_overflow_dont, /* complain_on_overflow */
212
         bfd_elf_generic_reloc, /* special_function */
213
         "R_AVR_HI8_LDI_NEG",   /* name */
214
         false,                 /* partial_inplace */
215
         0xffff,                /* src_mask */
216
         0xffff,                /* dst_mask */
217
         false),                /* pcrel_offset */
218
  /* A hegative high 6 bit absolute relocation of 22 bit address.
219
     For LDI command.  */
220
  HOWTO (R_AVR_HH8_LDI_NEG,     /* type */
221
         16,                    /* rightshift */
222
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
223
         8,                     /* bitsize */
224
         false,                 /* pc_relative */
225
         0,                      /* bitpos */
226
         complain_overflow_dont, /* complain_on_overflow */
227
         bfd_elf_generic_reloc, /* special_function */
228
         "R_AVR_HH8_LDI_NEG",   /* name */
229
         false,                 /* partial_inplace */
230
         0xffff,                /* src_mask */
231
         0xffff,                /* dst_mask */
232
         false),                /* pcrel_offset */
233
  /* A low 8 bit absolute relocation of 24 bit program memory address.
234
     For LDI command.  */
235
  HOWTO (R_AVR_LO8_LDI_PM,      /* type */
236
         1,                     /* rightshift */
237
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
238
         8,                     /* bitsize */
239
         false,                 /* pc_relative */
240
         0,                      /* bitpos */
241
         complain_overflow_dont, /* complain_on_overflow */
242
         bfd_elf_generic_reloc, /* special_function */
243
         "R_AVR_LO8_LDI_PM",    /* name */
244
         false,                 /* partial_inplace */
245
         0xffff,                /* src_mask */
246
         0xffff,                /* dst_mask */
247
         false),                /* pcrel_offset */
248
  /* A high 8 bit absolute relocation of 16 bit program memory address.
249
     For LDI command.  */
250
  HOWTO (R_AVR_HI8_LDI_PM,      /* type */
251
         9,                     /* rightshift */
252
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
253
         8,                     /* bitsize */
254
         false,                 /* pc_relative */
255
         0,                      /* bitpos */
256
         complain_overflow_dont, /* complain_on_overflow */
257
         bfd_elf_generic_reloc, /* special_function */
258
         "R_AVR_HI8_LDI_PM",    /* name */
259
         false,                 /* partial_inplace */
260
         0xffff,                /* src_mask */
261
         0xffff,                /* dst_mask */
262
         false),                /* pcrel_offset */
263
  /* A high 8 bit absolute relocation of 24 bit program memory address.
264
     For LDI command.  */
265
  HOWTO (R_AVR_HH8_LDI_PM,      /* type */
266
         17,                    /* rightshift */
267
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
268
         8,                     /* bitsize */
269
         false,                 /* pc_relative */
270
         0,                      /* bitpos */
271
         complain_overflow_dont, /* complain_on_overflow */
272
         bfd_elf_generic_reloc, /* special_function */
273
         "R_AVR_HH8_LDI_PM",    /* name */
274
         false,                 /* partial_inplace */
275
         0xffff,                /* src_mask */
276
         0xffff,                /* dst_mask */
277
         false),                /* pcrel_offset */
278
  /* A low 8 bit absolute relocation of a negative 24 bit
279
     program memory address.  For LDI command.  */
280
  HOWTO (R_AVR_LO8_LDI_PM_NEG,  /* type */
281
         1,                     /* rightshift */
282
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
283
         8,                     /* bitsize */
284
         false,                 /* pc_relative */
285
         0,                      /* bitpos */
286
         complain_overflow_dont, /* complain_on_overflow */
287
         bfd_elf_generic_reloc, /* special_function */
288
         "R_AVR_LO8_LDI_PM_NEG", /* name */
289
         false,                 /* partial_inplace */
290
         0xffff,                /* src_mask */
291
         0xffff,                /* dst_mask */
292
         false),                /* pcrel_offset */
293
  /* A high 8 bit absolute relocation of a negative 16 bit
294
     program memory address.  For LDI command.  */
295
  HOWTO (R_AVR_HI8_LDI_PM_NEG,  /* type */
296
         9,                     /* rightshift */
297
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
298
         8,                     /* bitsize */
299
         false,                 /* pc_relative */
300
         0,                      /* bitpos */
301
         complain_overflow_dont, /* complain_on_overflow */
302
         bfd_elf_generic_reloc, /* special_function */
303
         "R_AVR_HI8_LDI_PM_NEG", /* name */
304
         false,                 /* partial_inplace */
305
         0xffff,                /* src_mask */
306
         0xffff,                /* dst_mask */
307
         false),                /* pcrel_offset */
308
  /* A high 8 bit absolute relocation of a negative 24 bit
309
     program memory address.  For LDI command.  */
310
  HOWTO (R_AVR_HH8_LDI_PM_NEG,  /* type */
311
         17,                    /* rightshift */
312
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
313
         8,                     /* bitsize */
314
         false,                 /* pc_relative */
315
         0,                      /* bitpos */
316
         complain_overflow_dont, /* complain_on_overflow */
317
         bfd_elf_generic_reloc, /* special_function */
318
         "R_AVR_HH8_LDI_PM_NEG", /* name */
319
         false,                 /* partial_inplace */
320
         0xffff,                /* src_mask */
321
         0xffff,                /* dst_mask */
322
         false),                /* pcrel_offset */
323
  /* Relocation for CALL command in ATmega.  */
324
  HOWTO (R_AVR_CALL,            /* type */
325
         1,                     /* rightshift */
326
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
327
         23,                    /* bitsize */
328
         false,                 /* pc_relative */
329
         0,                      /* bitpos */
330
         complain_overflow_dont, /* complain_on_overflow */
331
         bfd_elf_generic_reloc, /* special_function */
332
         "R_AVR_CALL",          /* name */
333
         false,                 /* partial_inplace */
334
         0xffffffff,            /* src_mask */
335
         0xffffffff,            /* dst_mask */
336
         false)                 /* pcrel_offset */
337
};
338
 
339
/* Map BFD reloc types to AVR ELF reloc types.  */
340
 
341
struct avr_reloc_map
342
{
343
  bfd_reloc_code_real_type bfd_reloc_val;
344
  unsigned int elf_reloc_val;
345
};
346
 
347
 static const struct avr_reloc_map avr_reloc_map[] =
348
{
349
  { BFD_RELOC_NONE,                 R_AVR_NONE },
350
  { BFD_RELOC_32,                   R_AVR_32 },
351
  { BFD_RELOC_AVR_7_PCREL,          R_AVR_7_PCREL },
352
  { BFD_RELOC_AVR_13_PCREL,         R_AVR_13_PCREL },
353
  { BFD_RELOC_16,                   R_AVR_16 },
354
  { BFD_RELOC_AVR_16_PM,            R_AVR_16_PM },
355
  { BFD_RELOC_AVR_LO8_LDI,          R_AVR_LO8_LDI},
356
  { BFD_RELOC_AVR_HI8_LDI,          R_AVR_HI8_LDI },
357
  { BFD_RELOC_AVR_HH8_LDI,          R_AVR_HH8_LDI },
358
  { BFD_RELOC_AVR_LO8_LDI_NEG,      R_AVR_LO8_LDI_NEG },
359
  { BFD_RELOC_AVR_HI8_LDI_NEG,      R_AVR_HI8_LDI_NEG },
360
  { BFD_RELOC_AVR_HH8_LDI_NEG,      R_AVR_HH8_LDI_NEG },
361
  { BFD_RELOC_AVR_LO8_LDI_PM,       R_AVR_LO8_LDI_PM },
362
  { BFD_RELOC_AVR_HI8_LDI_PM,       R_AVR_HI8_LDI_PM },
363
  { BFD_RELOC_AVR_HH8_LDI_PM,       R_AVR_HH8_LDI_PM },
364
  { BFD_RELOC_AVR_LO8_LDI_PM_NEG,   R_AVR_LO8_LDI_PM_NEG },
365
  { BFD_RELOC_AVR_HI8_LDI_PM_NEG,   R_AVR_HI8_LDI_PM_NEG },
366
  { BFD_RELOC_AVR_HH8_LDI_PM_NEG,   R_AVR_HH8_LDI_PM_NEG },
367
  { BFD_RELOC_AVR_CALL,             R_AVR_CALL }
368
};
369
 
370
static reloc_howto_type *
371
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
372
     bfd *abfd;
373
     bfd_reloc_code_real_type code;
374
{
375
  unsigned int i;
376
 
377
  for (i = 0;
378
       i < sizeof (avr_reloc_map) / sizeof (struct avr_reloc_map);
379
       i++)
380
    {
381
      if (avr_reloc_map[i].bfd_reloc_val == code)
382
        return &elf_avr_howto_table[avr_reloc_map[i].elf_reloc_val];
383
    }
384
 
385
  return NULL;
386
}
387
 
388
/* Set the howto pointer for an AVR ELF reloc.  */
389
 
390
static void
391
avr_info_to_howto_rela (abfd, cache_ptr, dst)
392
     bfd *abfd;
393
     arelent *cache_ptr;
394
     Elf32_Internal_Rela *dst;
395
{
396
  unsigned int r_type;
397
 
398
  r_type = ELF32_R_TYPE (dst->r_info);
399
  BFD_ASSERT (r_type < (unsigned int) R_AVR_max);
400
  cache_ptr->howto = &elf_avr_howto_table[r_type];
401
}
402
 
403
static asection *
404
elf32_avr_gc_mark_hook (abfd, info, rel, h, sym)
405
     bfd *abfd;
406
     struct bfd_link_info *info;
407
     Elf_Internal_Rela *rel;
408
     struct elf_link_hash_entry *h;
409
     Elf_Internal_Sym *sym;
410
{
411
  if (h != NULL)
412
    {
413
      switch (ELF32_R_TYPE (rel->r_info))
414
        {
415
        default:
416
          switch (h->root.type)
417
            {
418
            case bfd_link_hash_defined:
419
            case bfd_link_hash_defweak:
420
              return h->root.u.def.section;
421
 
422
            case bfd_link_hash_common:
423
              return h->root.u.c.p->section;
424
 
425
            default:
426
              break;
427
            }
428
        }
429
    }
430
  else
431
    {
432
      if (!(elf_bad_symtab (abfd)
433
            && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
434
          && !((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
435
               && sym->st_shndx != SHN_COMMON))
436
        {
437
          return bfd_section_from_elf_index (abfd, sym->st_shndx);
438
        }
439
    }
440
  return NULL;
441
}
442
 
443
static boolean
444
elf32_avr_gc_sweep_hook (abfd, info, sec, relocs)
445
     bfd *abfd;
446
     struct bfd_link_info *info;
447
     asection *sec;
448
     const Elf_Internal_Rela *relocs;
449
{
450
  /* We don't use got and plt entries for avr.  */
451
  return true;
452
}
453
 
454
/* Look through the relocs for a section during the first phase.
455
   Since we don't do .gots or .plts, we just need to consider the
456
   virtual table relocs for gc.  */
457
 
458
static boolean
459
elf32_avr_check_relocs (abfd, info, sec, relocs)
460
     bfd *abfd;
461
     struct bfd_link_info *info;
462
     asection *sec;
463
     const Elf_Internal_Rela *relocs;
464
{
465
  Elf_Internal_Shdr *symtab_hdr;
466
  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
467
  const Elf_Internal_Rela *rel;
468
  const Elf_Internal_Rela *rel_end;
469
 
470
  if (info->relocateable)
471
    return true;
472
 
473
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
474
  sym_hashes = elf_sym_hashes (abfd);
475
  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
476
  if (!elf_bad_symtab (abfd))
477
    sym_hashes_end -= symtab_hdr->sh_info;
478
 
479
  rel_end = relocs + sec->reloc_count;
480
  for (rel = relocs; rel < rel_end; rel++)
481
    {
482
      struct elf_link_hash_entry *h;
483
      unsigned long r_symndx;
484
 
485
      r_symndx = ELF32_R_SYM (rel->r_info);
486
      if (r_symndx < symtab_hdr->sh_info)
487
        h = NULL;
488
      else
489
        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
490
    }
491
 
492
  return true;
493
}
494
 
495
/* Perform a single relocation.  By default we use the standard BFD
496
   routines, but a few relocs, we have to do them ourselves.  */
497
 
498
static bfd_reloc_status_type
499
avr_final_link_relocate (howto, input_bfd, input_section,
500
                         contents, rel, relocation)
501
     reloc_howto_type *  howto;
502
     bfd *               input_bfd;
503
     asection *          input_section;
504
     bfd_byte *          contents;
505
     Elf_Internal_Rela * rel;
506
     bfd_vma             relocation;
507
{
508
  bfd_reloc_status_type r = bfd_reloc_ok;
509
  bfd_vma               x;
510
  bfd_signed_vma        srel;
511
 
512
  switch (howto->type)
513
    {
514
    case R_AVR_7_PCREL:
515
      contents += rel->r_offset;
516
      srel = (bfd_signed_vma) relocation;
517
      srel += rel->r_addend;
518
      srel -= rel->r_offset;
519
      srel -= 2;        /* Branch instructions add 2 to the PC... */
520
      srel -= (input_section->output_section->vma +
521
               input_section->output_offset);
522
 
523
      if (srel & 1)
524
        return bfd_reloc_outofrange;
525
      if (srel > ((1 << 7) - 1) || (srel < - (1 << 7)))
526
        return bfd_reloc_overflow;
527
      x = bfd_get_16 (input_bfd, contents);
528
      x = (x & 0xfc07) | (((srel >> 1) << 3) & 0x3f8);
529
      bfd_put_16 (input_bfd, x, contents);
530
      break;
531
 
532
    case R_AVR_13_PCREL:
533
      contents   += rel->r_offset;
534
      srel = (bfd_signed_vma) relocation;
535
      srel += rel->r_addend;
536
      srel -= rel->r_offset;
537
      srel -= 2;        /* Branch instructions add 2 to the PC... */
538
      srel -= (input_section->output_section->vma +
539
               input_section->output_offset);
540
 
541
      if (srel & 1)
542
        return bfd_reloc_outofrange;
543
 
544
      /* AVR addresses commands as words.  */
545
      srel >>= 1;
546
 
547
      /* Check for overflow.  */
548
      if (srel < -2048 || srel > 2047)
549
        {
550
          /* Apply WRAPAROUND if possible.  */
551
          if (bfd_get_mach (input_bfd) == bfd_mach_avr2)
552
            {
553
              if (srel > 2047)
554
                srel -= 4096;
555
              else
556
                srel += 4096;
557
            }
558
          else
559
            return bfd_reloc_overflow;
560
        }
561
 
562
      x = bfd_get_16 (input_bfd, contents);
563
      x = (x & 0xf000) | (srel & 0xfff);
564
      bfd_put_16 (input_bfd, x, contents);
565
      break;
566
 
567
    case R_AVR_LO8_LDI:
568
      contents += rel->r_offset;
569
      srel = (bfd_signed_vma) relocation + rel->r_addend;
570
      x = bfd_get_16 (input_bfd, contents);
571
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
572
      bfd_put_16 (input_bfd, x, contents);
573
      break;
574
 
575
    case R_AVR_HI8_LDI:
576
      contents += rel->r_offset;
577
      srel = (bfd_signed_vma) relocation + rel->r_addend;
578
      srel = (srel >> 8) & 0xff;
579
      x = bfd_get_16 (input_bfd, contents);
580
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
581
      bfd_put_16 (input_bfd, x, contents);
582
      break;
583
 
584
    case R_AVR_HH8_LDI:
585
      contents += rel->r_offset;
586
      srel = (bfd_signed_vma) relocation + rel->r_addend;
587
      srel = (srel >> 16) & 0xff;
588
      x = bfd_get_16 (input_bfd, contents);
589
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
590
      bfd_put_16 (input_bfd, x, contents);
591
      break;
592
 
593
    case R_AVR_LO8_LDI_NEG:
594
      contents += rel->r_offset;
595
      srel = (bfd_signed_vma) relocation + rel->r_addend;
596
      srel = -srel;
597
      x = bfd_get_16 (input_bfd, contents);
598
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
599
      bfd_put_16 (input_bfd, x, contents);
600
      break;
601
 
602
    case R_AVR_HI8_LDI_NEG:
603
      contents += rel->r_offset;
604
      srel = (bfd_signed_vma) relocation + rel->r_addend;
605
      srel = -srel;
606
      srel = (srel >> 8) & 0xff;
607
      x = bfd_get_16 (input_bfd, contents);
608
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
609
      bfd_put_16 (input_bfd, x, contents);
610
      break;
611
 
612
    case R_AVR_HH8_LDI_NEG:
613
      contents += rel->r_offset;
614
      srel = (bfd_signed_vma) relocation + rel->r_addend;
615
      srel = -srel;
616
      srel = (srel >> 16) & 0xff;
617
      x = bfd_get_16 (input_bfd, contents);
618
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
619
      bfd_put_16 (input_bfd, x, contents);
620
      break;
621
 
622
    case R_AVR_LO8_LDI_PM:
623
      contents += rel->r_offset;
624
      srel = (bfd_signed_vma) relocation + rel->r_addend;
625
      if (srel & 1)
626
        return bfd_reloc_outofrange;
627
      srel = srel >> 1;
628
      x = bfd_get_16 (input_bfd, contents);
629
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
630
      bfd_put_16 (input_bfd, x, contents);
631
      break;
632
 
633
    case R_AVR_HI8_LDI_PM:
634
      contents += rel->r_offset;
635
      srel = (bfd_signed_vma) relocation + rel->r_addend;
636
      if (srel & 1)
637
        return bfd_reloc_outofrange;
638
      srel = srel >> 1;
639
      srel = (srel >> 8) & 0xff;
640
      x = bfd_get_16 (input_bfd, contents);
641
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
642
      bfd_put_16 (input_bfd, x, contents);
643
      break;
644
 
645
    case R_AVR_HH8_LDI_PM:
646
      contents += rel->r_offset;
647
      srel = (bfd_signed_vma) relocation + rel->r_addend;
648
      if (srel & 1)
649
        return bfd_reloc_outofrange;
650
      srel = srel >> 1;
651
      srel = (srel >> 16) & 0xff;
652
      x = bfd_get_16 (input_bfd, contents);
653
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
654
      bfd_put_16 (input_bfd, x, contents);
655
      break;
656
 
657
    case R_AVR_LO8_LDI_PM_NEG:
658
      contents += rel->r_offset;
659
      srel = (bfd_signed_vma) relocation + rel->r_addend;
660
      srel = -srel;
661
      if (srel & 1)
662
        return bfd_reloc_outofrange;
663
      srel = srel >> 1;
664
      x = bfd_get_16 (input_bfd, contents);
665
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
666
      bfd_put_16 (input_bfd, x, contents);
667
      break;
668
 
669
    case R_AVR_HI8_LDI_PM_NEG:
670
      contents += rel->r_offset;
671
      srel = (bfd_signed_vma) relocation + rel->r_addend;
672
      srel = -srel;
673
      if (srel & 1)
674
        return bfd_reloc_outofrange;
675
      srel = srel >> 1;
676
      srel = (srel >> 8) & 0xff;
677
      x = bfd_get_16 (input_bfd, contents);
678
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
679
      bfd_put_16 (input_bfd, x, contents);
680
      break;
681
 
682
    case R_AVR_HH8_LDI_PM_NEG:
683
      contents += rel->r_offset;
684
      srel = (bfd_signed_vma) relocation + rel->r_addend;
685
      srel = -srel;
686
      if (srel & 1)
687
        return bfd_reloc_outofrange;
688
      srel = srel >> 1;
689
      srel = (srel >> 16) & 0xff;
690
      x = bfd_get_16 (input_bfd, contents);
691
      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
692
      bfd_put_16 (input_bfd, x, contents);
693
      break;
694
 
695
    case R_AVR_CALL:
696
      contents += rel->r_offset;
697
      srel = (bfd_signed_vma) relocation + rel->r_addend;
698
      if (srel & 1)
699
        return bfd_reloc_outofrange;
700
      srel = srel >> 1;
701
      x = bfd_get_16 (input_bfd, contents);
702
      x |= ((srel & 0x10000) | ((srel << 3) & 0x1f00000)) >> 16;
703
      bfd_put_16 (input_bfd, x, contents);
704
      bfd_put_16 (input_bfd, srel & 0xffff, contents+2);
705
      break;
706
 
707
    default:
708
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
709
                                    contents, rel->r_offset,
710
                                    relocation, rel->r_addend);
711
    }
712
 
713
  return r;
714
}
715
 
716
/* Relocate an AVR ELF section.  */
717
static boolean
718
elf32_avr_relocate_section (output_bfd, info, input_bfd, input_section,
719
                            contents, relocs, local_syms, local_sections)
720
     bfd *output_bfd;
721
     struct bfd_link_info *info;
722
     bfd *input_bfd;
723
     asection *input_section;
724
     bfd_byte *contents;
725
     Elf_Internal_Rela *relocs;
726
     Elf_Internal_Sym *local_syms;
727
     asection **local_sections;
728
{
729
  Elf_Internal_Shdr *           symtab_hdr;
730
  struct elf_link_hash_entry ** sym_hashes;
731
  Elf_Internal_Rela *           rel;
732
  Elf_Internal_Rela *           relend;
733
 
734
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
735
  sym_hashes = elf_sym_hashes (input_bfd);
736
  relend     = relocs + input_section->reloc_count;
737
 
738
  for (rel = relocs; rel < relend; rel ++)
739
    {
740
      reloc_howto_type *           howto;
741
      unsigned long                r_symndx;
742
      Elf_Internal_Sym *           sym;
743
      asection *                   sec;
744
      struct elf_link_hash_entry * h;
745
      bfd_vma                      relocation;
746
      bfd_reloc_status_type        r;
747
      const char *                 name = NULL;
748
      int                          r_type;
749
 
750
      r_type = ELF32_R_TYPE (rel->r_info);
751
      r_symndx = ELF32_R_SYM (rel->r_info);
752
 
753
      if (info->relocateable)
754
        {
755
          /* This is a relocateable link.  We don't have to change
756
             anything, unless the reloc is against a section symbol,
757
             in which case we have to adjust according to where the
758
             section symbol winds up in the output section.  */
759
          if (r_symndx < symtab_hdr->sh_info)
760
            {
761
              sym = local_syms + r_symndx;
762
 
763
              if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
764
                {
765
                  sec = local_sections [r_symndx];
766
                  rel->r_addend += sec->output_offset + sym->st_value;
767
                }
768
            }
769
 
770
          continue;
771
        }
772
 
773
      /* This is a final link.  */
774
      howto  = elf_avr_howto_table + ELF32_R_TYPE (rel->r_info);
775
      h      = NULL;
776
      sym    = NULL;
777
      sec    = NULL;
778
 
779
      if (r_symndx < symtab_hdr->sh_info)
780
        {
781
          sym = local_syms + r_symndx;
782
          sec = local_sections [r_symndx];
783
          relocation = (sec->output_section->vma
784
                        + sec->output_offset
785
                        + sym->st_value);
786
 
787
          name = bfd_elf_string_from_elf_section
788
            (input_bfd, symtab_hdr->sh_link, sym->st_name);
789
          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
790
        }
791
      else
792
        {
793
          h = sym_hashes [r_symndx - symtab_hdr->sh_info];
794
 
795
          while (h->root.type == bfd_link_hash_indirect
796
                 || h->root.type == bfd_link_hash_warning)
797
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
798
 
799
          name = h->root.root.string;
800
 
801
          if (h->root.type == bfd_link_hash_defined
802
              || h->root.type == bfd_link_hash_defweak)
803
            {
804
              sec = h->root.u.def.section;
805
              relocation = (h->root.u.def.value
806
                            + sec->output_section->vma
807
                            + sec->output_offset);
808
            }
809
          else if (h->root.type == bfd_link_hash_undefweak)
810
            {
811
              relocation = 0;
812
            }
813
          else
814
            {
815
              if (! ((*info->callbacks->undefined_symbol)
816
                     (info, h->root.root.string, input_bfd,
817
                      input_section, rel->r_offset, true)))
818
                return false;
819
              relocation = 0;
820
            }
821
        }
822
 
823
      r = avr_final_link_relocate (howto, input_bfd, input_section,
824
                                   contents, rel, relocation);
825
 
826
      if (r != bfd_reloc_ok)
827
        {
828
          const char * msg = (const char *) NULL;
829
 
830
          switch (r)
831
            {
832
            case bfd_reloc_overflow:
833
              r = info->callbacks->reloc_overflow
834
                (info, name, howto->name, (bfd_vma) 0,
835
                 input_bfd, input_section, rel->r_offset);
836
              break;
837
 
838
            case bfd_reloc_undefined:
839
              r = info->callbacks->undefined_symbol
840
                (info, name, input_bfd, input_section, rel->r_offset, true);
841
              break;
842
 
843
            case bfd_reloc_outofrange:
844
              msg = _("internal error: out of range error");
845
              break;
846
 
847
            case bfd_reloc_notsupported:
848
              msg = _("internal error: unsupported relocation error");
849
              break;
850
 
851
            case bfd_reloc_dangerous:
852
              msg = _("internal error: dangerous relocation");
853
              break;
854
 
855
            default:
856
              msg = _("internal error: unknown error");
857
              break;
858
            }
859
 
860
          if (msg)
861
            r = info->callbacks->warning
862
              (info, msg, name, input_bfd, input_section, rel->r_offset);
863
 
864
          if (! r)
865
            return false;
866
        }
867
    }
868
 
869
  return true;
870
}
871
 
872
/* The final processing done just before writing out a AVR ELF object
873
   file.  This gets the AVR architecture right based on the machine
874
   number.  */
875
 
876
static void
877
bfd_elf_avr_final_write_processing (abfd, linker)
878
     bfd *abfd;
879
     boolean linker ATTRIBUTE_UNUSED;
880
{
881
  unsigned long val;
882
 
883
  switch (bfd_get_mach (abfd))
884
    {
885
    default:
886
    case bfd_mach_avr2:
887
      val = E_AVR_MACH_AVR2;
888
      break;
889
 
890
    case bfd_mach_avr1:
891
      val = E_AVR_MACH_AVR1;
892
      break;
893
 
894
    case bfd_mach_avr3:
895
      val = E_AVR_MACH_AVR3;
896
      break;
897
 
898
    case bfd_mach_avr4:
899
      val = E_AVR_MACH_AVR4;
900
      break;
901
 
902
    }
903
 
904
  elf_elfheader (abfd)->e_machine = EM_AVR;
905
  elf_elfheader (abfd)->e_flags &= ~ EF_AVR_MACH;
906
  elf_elfheader (abfd)->e_flags |= val;
907
}
908
 
909
/* Set the right machine number.  */
910
 
911
static boolean
912
elf32_avr_object_p (abfd)
913
     bfd *abfd;
914
{
915
  int e_set = bfd_mach_avr2;
916
  if (elf_elfheader (abfd)->e_machine == EM_AVR)
917
    {
918
      int e_mach = elf_elfheader (abfd)->e_flags & EF_AVR_MACH;
919
      switch (e_mach)
920
        {
921
        default:
922
        case E_AVR_MACH_AVR2:
923
          e_set = bfd_mach_avr2;
924
          break;
925
 
926
        case E_AVR_MACH_AVR1:
927
          e_set = bfd_mach_avr1;
928
          break;
929
 
930
        case E_AVR_MACH_AVR3:
931
          e_set = bfd_mach_avr3;
932
          break;
933
 
934
        case E_AVR_MACH_AVR4:
935
          e_set = bfd_mach_avr4;
936
          break;
937
        }
938
    }
939
  return bfd_default_set_arch_mach (abfd, bfd_arch_avr,
940
                                    e_set);
941
}
942
 
943
 
944
#define ELF_ARCH                bfd_arch_avr
945
#define ELF_MACHINE_CODE        EM_AVR
946
#define ELF_MAXPAGESIZE         1
947
 
948
#define TARGET_LITTLE_SYM       bfd_elf32_avr_vec
949
#define TARGET_LITTLE_NAME      "elf32-avr"
950
 
951
#define elf_info_to_howto                    avr_info_to_howto_rela
952
#define elf_info_to_howto_rel                NULL
953
#define elf_backend_relocate_section         elf32_avr_relocate_section
954
#define elf_backend_gc_mark_hook             elf32_avr_gc_mark_hook
955
#define elf_backend_gc_sweep_hook            elf32_avr_gc_sweep_hook
956
#define elf_backend_check_relocs             elf32_avr_check_relocs
957
#define elf_backend_can_gc_sections          1
958
#define elf_backend_final_write_processing \
959
                                        bfd_elf_avr_final_write_processing
960
#define elf_backend_object_p            elf32_avr_object_p
961
 
962
 
963
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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