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

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [bfd/] [elf32-avr.c] - Blame information for rev 1182

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

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

powered by: WebSVN 2.1.0

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