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

Subversion Repositories or1k

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

powered by: WebSVN 2.1.0

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