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

Subversion Repositories or1k_old

[/] [or1k_old/] [tags/] [VER_5_3/] [gdb-5.3/] [bfd/] [elf32-m68hc11.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* Motorola 68HC11-specific support for 32-bit ELF
2
   Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3
   Contributed by Stephane Carrez (stcarrez@nerim.fr)
4
   (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
5
 
6
This file is part of BFD, the Binary File Descriptor library.
7
 
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
12
 
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
 
22
#include "bfd.h"
23
#include "sysdep.h"
24
#include "bfdlink.h"
25
#include "libbfd.h"
26
#include "elf-bfd.h"
27
#include "elf/m68hc11.h"
28
 
29
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
30
  PARAMS ((bfd *, bfd_reloc_code_real_type));
31
static void m68hc11_info_to_howto_rel
32
  PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
33
 
34
static bfd_reloc_status_type m68hc11_elf_ignore_reloc
35
  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
36
 
37
/* GC mark and sweep.  */
38
static asection *elf32_m68hc11_gc_mark_hook
39
  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
40
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
41
static boolean elf32_m68hc11_gc_sweep_hook
42
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
43
           const Elf_Internal_Rela *));
44
static boolean elf32_m68hc11_check_relocs
45
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
46
           const Elf_Internal_Rela *));
47
static boolean elf32_m68hc11_relocate_section
48
  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
49
           Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
50
static boolean m68hc11_elf_relax_section
51
  PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
52
static void m68hc11_elf_relax_delete_bytes
53
  PARAMS ((bfd *, asection *, bfd_vma, int));
54
static void m68hc11_relax_group
55
  PARAMS ((bfd *, asection *, bfd_byte *, unsigned,
56
           unsigned long, unsigned long));
57
static int compare_reloc PARAMS ((const void *, const void *));
58
 
59
 
60
boolean _bfd_m68hc11_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
61
boolean _bfd_m68hc11_elf_set_private_flags PARAMS ((bfd *, flagword));
62
boolean _bfd_m68hc11_elf_print_private_bfd_data PARAMS ((bfd *, PTR));
63
 
64
/* Use REL instead of RELA to save space */
65
#define USE_REL
66
 
67
/* The Motorola 68HC11 microcontroler only addresses 64Kb.
68
   We must handle 8 and 16-bit relocations.  The 32-bit relocation
69
   is defined but not used except by gas when -gstabs is used (which
70
   is wrong).
71
   The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
72
static reloc_howto_type elf_m68hc11_howto_table[] = {
73
  /* This reloc does nothing.  */
74
  HOWTO (R_M68HC11_NONE,        /* type */
75
         0,                      /* rightshift */
76
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
77
         32,                    /* bitsize */
78
         false,                 /* pc_relative */
79
         0,                      /* bitpos */
80
         complain_overflow_dont,/* complain_on_overflow */
81
         bfd_elf_generic_reloc, /* special_function */
82
         "R_M68HC11_NONE",      /* name */
83
         false,                 /* partial_inplace */
84
         0,                      /* src_mask */
85
         0,                      /* dst_mask */
86
         false),                /* pcrel_offset */
87
 
88
  /* A 8 bit absolute relocation */
89
  HOWTO (R_M68HC11_8,           /* type */
90
         0,                      /* rightshift */
91
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
92
         8,                     /* bitsize */
93
         false,                 /* pc_relative */
94
         0,                      /* bitpos */
95
         complain_overflow_bitfield,    /* complain_on_overflow */
96
         bfd_elf_generic_reloc, /* special_function */
97
         "R_M68HC11_8",         /* name */
98
         false,                 /* partial_inplace */
99
         0x00ff,                /* src_mask */
100
         0x00ff,                /* dst_mask */
101
         false),                /* pcrel_offset */
102
 
103
  /* A 8 bit absolute relocation (upper address) */
104
  HOWTO (R_M68HC11_HI8,         /* type */
105
         8,                     /* rightshift */
106
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
107
         8,                     /* bitsize */
108
         false,                 /* pc_relative */
109
         0,                      /* bitpos */
110
         complain_overflow_bitfield,    /* complain_on_overflow */
111
         bfd_elf_generic_reloc, /* special_function */
112
         "R_M68HC11_HI8",       /* name */
113
         false,                 /* partial_inplace */
114
         0x00ff,                /* src_mask */
115
         0x00ff,                /* dst_mask */
116
         false),                /* pcrel_offset */
117
 
118
  /* A 8 bit absolute relocation (upper address) */
119
  HOWTO (R_M68HC11_LO8,         /* type */
120
         0,                      /* rightshift */
121
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
122
         8,                     /* bitsize */
123
         false,                 /* pc_relative */
124
         0,                      /* bitpos */
125
         complain_overflow_dont,        /* complain_on_overflow */
126
         bfd_elf_generic_reloc, /* special_function */
127
         "R_M68HC11_LO8",       /* name */
128
         false,                 /* partial_inplace */
129
         0x00ff,                /* src_mask */
130
         0x00ff,                /* dst_mask */
131
         false),                /* pcrel_offset */
132
 
133
  /* A 8 bit PC-rel relocation */
134
  HOWTO (R_M68HC11_PCREL_8,     /* type */
135
         0,                      /* rightshift */
136
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
137
         8,                     /* bitsize */
138
         true,                  /* pc_relative */
139
         0,                      /* bitpos */
140
         complain_overflow_bitfield,    /* complain_on_overflow */
141
         bfd_elf_generic_reloc, /* special_function */
142
         "R_M68HC11_PCREL_8",   /* name */
143
         false,                 /* partial_inplace */
144
         0x00ff,                /* src_mask */
145
         0x00ff,                /* dst_mask */
146
         false),                /* pcrel_offset */
147
 
148
  /* A 16 bit absolute relocation */
149
  HOWTO (R_M68HC11_16,          /* type */
150
         0,                      /* rightshift */
151
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
152
         16,                    /* bitsize */
153
         false,                 /* pc_relative */
154
         0,                      /* bitpos */
155
         complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
156
         bfd_elf_generic_reloc, /* special_function */
157
         "R_M68HC11_16",        /* name */
158
         false,                 /* partial_inplace */
159
         0xffff,                /* src_mask */
160
         0xffff,                /* dst_mask */
161
         false),                /* pcrel_offset */
162
 
163
  /* A 32 bit absolute relocation.  This one is never used for the
164
     code relocation.  It's used by gas for -gstabs generation.  */
165
  HOWTO (R_M68HC11_32,          /* type */
166
         0,                      /* rightshift */
167
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
168
         32,                    /* bitsize */
169
         false,                 /* pc_relative */
170
         0,                      /* bitpos */
171
         complain_overflow_bitfield,    /* complain_on_overflow */
172
         bfd_elf_generic_reloc, /* special_function */
173
         "R_M68HC11_32",        /* name */
174
         false,                 /* partial_inplace */
175
         0xffffffff,            /* src_mask */
176
         0xffffffff,            /* dst_mask */
177
         false),                /* pcrel_offset */
178
 
179
  /* A 3 bit absolute relocation */
180
  HOWTO (R_M68HC11_3B,          /* type */
181
         0,                      /* rightshift */
182
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
183
         3,                     /* bitsize */
184
         false,                 /* pc_relative */
185
         0,                      /* bitpos */
186
         complain_overflow_bitfield,    /* complain_on_overflow */
187
         bfd_elf_generic_reloc, /* special_function */
188
         "R_M68HC11_4B",        /* name */
189
         false,                 /* partial_inplace */
190
         0x003,                 /* src_mask */
191
         0x003,                 /* dst_mask */
192
         false),                /* pcrel_offset */
193
 
194
  /* A 16 bit PC-rel relocation */
195
  HOWTO (R_M68HC11_PCREL_16,    /* type */
196
         0,                      /* rightshift */
197
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
198
         16,                    /* bitsize */
199
         true,                  /* pc_relative */
200
         0,                      /* bitpos */
201
         complain_overflow_dont,        /* complain_on_overflow */
202
         bfd_elf_generic_reloc, /* special_function */
203
         "R_M68HC11_PCREL_16",  /* name */
204
         false,                 /* partial_inplace */
205
         0xffff,                /* src_mask */
206
         0xffff,                /* dst_mask */
207
         false),                /* pcrel_offset */
208
 
209
  /* GNU extension to record C++ vtable hierarchy */
210
  HOWTO (R_M68HC11_GNU_VTINHERIT,       /* type */
211
         0,                      /* rightshift */
212
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
213
         0,                      /* bitsize */
214
         false,                 /* pc_relative */
215
         0,                      /* bitpos */
216
         complain_overflow_dont,        /* complain_on_overflow */
217
         NULL,                  /* special_function */
218
         "R_M68HC11_GNU_VTINHERIT",     /* name */
219
         false,                 /* partial_inplace */
220
         0,                      /* src_mask */
221
         0,                      /* dst_mask */
222
         false),                /* pcrel_offset */
223
 
224
  /* GNU extension to record C++ vtable member usage */
225
  HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
226
         0,                      /* rightshift */
227
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
228
         0,                      /* bitsize */
229
         false,                 /* pc_relative */
230
         0,                      /* bitpos */
231
         complain_overflow_dont,        /* complain_on_overflow */
232
         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
233
         "R_M68HC11_GNU_VTENTRY",       /* name */
234
         false,                 /* partial_inplace */
235
         0,                      /* src_mask */
236
         0,                      /* dst_mask */
237
         false),                /* pcrel_offset */
238
 
239
  /* A 24 bit relocation */
240
  HOWTO (R_M68HC11_24,          /* type */
241
         0,                      /* rightshift */
242
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
243
         24,                    /* bitsize */
244
         false,                 /* pc_relative */
245
         0,                      /* bitpos */
246
         complain_overflow_bitfield,    /* complain_on_overflow */
247
         bfd_elf_generic_reloc, /* special_function */
248
         "R_M68HC11_24",        /* name */
249
         false,                 /* partial_inplace */
250
         0xffff,                /* src_mask */
251
         0xffff,                /* dst_mask */
252
         false),                /* pcrel_offset */
253
 
254
  /* A 16-bit low relocation */
255
  HOWTO (R_M68HC11_LO16,        /* type */
256
         0,                      /* rightshift */
257
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
258
         16,                    /* bitsize */
259
         false,                 /* pc_relative */
260
         0,                      /* bitpos */
261
         complain_overflow_bitfield,    /* complain_on_overflow */
262
         bfd_elf_generic_reloc, /* special_function */
263
         "R_M68HC11_LO16",      /* name */
264
         false,                 /* partial_inplace */
265
         0xffff,                /* src_mask */
266
         0xffff,                /* dst_mask */
267
         false),                /* pcrel_offset */
268
 
269
  /* A page relocation */
270
  HOWTO (R_M68HC11_PAGE,        /* type */
271
         0,                      /* rightshift */
272
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
273
         8,                     /* bitsize */
274
         false,                 /* pc_relative */
275
         0,                      /* bitpos */
276
         complain_overflow_bitfield,    /* complain_on_overflow */
277
         bfd_elf_generic_reloc, /* special_function */
278
         "R_M68HC11_PAGE",      /* name */
279
         false,                 /* partial_inplace */
280
         0x00ff,                /* src_mask */
281
         0x00ff,                /* dst_mask */
282
         false),                /* pcrel_offset */
283
 
284
  EMPTY_HOWTO (14),
285
  EMPTY_HOWTO (15),
286
  EMPTY_HOWTO (16),
287
  EMPTY_HOWTO (17),
288
  EMPTY_HOWTO (18),
289
  EMPTY_HOWTO (19),
290
 
291
  /* Mark beginning of a jump instruction (any form).  */
292
  HOWTO (R_M68HC11_RL_JUMP,     /* type */
293
         0,                      /* rightshift */
294
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
295
         0,                      /* bitsize */
296
         false,                 /* pc_relative */
297
         0,                      /* bitpos */
298
         complain_overflow_dont,        /* complain_on_overflow */
299
         m68hc11_elf_ignore_reloc,      /* special_function */
300
         "R_M68HC11_RL_JUMP",   /* name */
301
         true,                  /* partial_inplace */
302
         0,                      /* src_mask */
303
         0,                      /* dst_mask */
304
         true),                 /* pcrel_offset */
305
 
306
  /* Mark beginning of Gcc relaxation group instruction.  */
307
  HOWTO (R_M68HC11_RL_GROUP,    /* type */
308
         0,                      /* rightshift */
309
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
310
         0,                      /* bitsize */
311
         false,                 /* pc_relative */
312
         0,                      /* bitpos */
313
         complain_overflow_dont,        /* complain_on_overflow */
314
         m68hc11_elf_ignore_reloc,      /* special_function */
315
         "R_M68HC11_RL_GROUP",  /* name */
316
         true,                  /* partial_inplace */
317
         0,                      /* src_mask */
318
         0,                      /* dst_mask */
319
         true),                 /* pcrel_offset */
320
};
321
 
322
/* Map BFD reloc types to M68HC11 ELF reloc types.  */
323
 
324
struct m68hc11_reloc_map
325
{
326
  bfd_reloc_code_real_type bfd_reloc_val;
327
  unsigned char elf_reloc_val;
328
};
329
 
330
static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
331
  {BFD_RELOC_NONE, R_M68HC11_NONE,},
332
  {BFD_RELOC_8, R_M68HC11_8},
333
  {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
334
  {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
335
  {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
336
  {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
337
  {BFD_RELOC_16, R_M68HC11_16},
338
  {BFD_RELOC_32, R_M68HC11_32},
339
  {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
340
 
341
  {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
342
  {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
343
 
344
  {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
345
  {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
346
  {BFD_RELOC_M68HC11_24, R_M68HC11_24},
347
 
348
  {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
349
  {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
350
};
351
 
352
static reloc_howto_type *
353
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
354
     bfd *abfd ATTRIBUTE_UNUSED;
355
     bfd_reloc_code_real_type code;
356
{
357
  unsigned int i;
358
 
359
  for (i = 0;
360
       i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
361
       i++)
362
    {
363
      if (m68hc11_reloc_map[i].bfd_reloc_val == code)
364
        return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
365
    }
366
 
367
  return NULL;
368
}
369
 
370
/* This function is used for relocs which are only used for relaxing,
371
   which the linker should otherwise ignore.  */
372
 
373
static bfd_reloc_status_type
374
m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
375
                          output_bfd, error_message)
376
     bfd *abfd ATTRIBUTE_UNUSED;
377
     arelent *reloc_entry;
378
     asymbol *symbol ATTRIBUTE_UNUSED;
379
     PTR data ATTRIBUTE_UNUSED;
380
     asection *input_section;
381
     bfd *output_bfd;
382
     char **error_message ATTRIBUTE_UNUSED;
383
{
384
  if (output_bfd != NULL)
385
    reloc_entry->address += input_section->output_offset;
386
  return bfd_reloc_ok;
387
}
388
 
389
/* Set the howto pointer for an M68HC11 ELF reloc.  */
390
 
391
static void
392
m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
393
     bfd *abfd ATTRIBUTE_UNUSED;
394
     arelent *cache_ptr;
395
     Elf32_Internal_Rel *dst;
396
{
397
  unsigned int r_type;
398
 
399
  r_type = ELF32_R_TYPE (dst->r_info);
400
  BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
401
  cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
402
}
403
 
404
static asection *
405
elf32_m68hc11_gc_mark_hook (sec, info, rel, h, sym)
406
     asection *sec;
407
     struct bfd_link_info *info ATTRIBUTE_UNUSED;
408
     Elf_Internal_Rela *rel;
409
     struct elf_link_hash_entry *h;
410
     Elf_Internal_Sym *sym;
411
{
412
  if (h != NULL)
413
    {
414
      switch (ELF32_R_TYPE (rel->r_info))
415
        {
416
        default:
417
          switch (h->root.type)
418
            {
419
            case bfd_link_hash_defined:
420
            case bfd_link_hash_defweak:
421
              return h->root.u.def.section;
422
 
423
            case bfd_link_hash_common:
424
              return h->root.u.c.p->section;
425
 
426
            default:
427
              break;
428
            }
429
        }
430
    }
431
  else
432
    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
433
 
434
  return NULL;
435
}
436
 
437
static boolean
438
elf32_m68hc11_gc_sweep_hook (abfd, info, sec, relocs)
439
     bfd *abfd ATTRIBUTE_UNUSED;
440
     struct bfd_link_info *info ATTRIBUTE_UNUSED;
441
     asection *sec ATTRIBUTE_UNUSED;
442
     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
443
{
444
  /* We don't use got and plt entries for 68hc11/68hc12.  */
445
  return true;
446
}
447
 
448
struct m68hc11_direct_relax
449
{
450
  const char *name;
451
  unsigned char code;
452
  unsigned char direct_code;
453
} m68hc11_direct_relax_table[] = {
454
  { "adca", 0xB9, 0x99 },
455
  { "adcb", 0xF9, 0xD9 },
456
  { "adda", 0xBB, 0x9B },
457
  { "addb", 0xFB, 0xDB },
458
  { "addd", 0xF3, 0xD3 },
459
  { "anda", 0xB4, 0x94 },
460
  { "andb", 0xF4, 0xD4 },
461
  { "cmpa", 0xB1, 0x91 },
462
  { "cmpb", 0xF1, 0xD1 },
463
  { "cpd",  0xB3, 0x93 },
464
  { "cpxy", 0xBC, 0x9C },
465
/* { "cpy",  0xBC, 0x9C }, */
466
  { "eora", 0xB8, 0x98 },
467
  { "eorb", 0xF8, 0xD8 },
468
  { "jsr",  0xBD, 0x9D },
469
  { "ldaa", 0xB6, 0x96 },
470
  { "ldab", 0xF6, 0xD6 },
471
  { "ldd",  0xFC, 0xDC },
472
  { "lds",  0xBE, 0x9E },
473
  { "ldxy", 0xFE, 0xDE },
474
  /*  { "ldy",  0xFE, 0xDE },*/
475
  { "oraa", 0xBA, 0x9A },
476
  { "orab", 0xFA, 0xDA },
477
  { "sbca", 0xB2, 0x92 },
478
  { "sbcb", 0xF2, 0xD2 },
479
  { "staa", 0xB7, 0x97 },
480
  { "stab", 0xF7, 0xD7 },
481
  { "std",  0xFD, 0xDD },
482
  { "sts",  0xBF, 0x9F },
483
  { "stxy", 0xFF, 0xDF },
484
  /*  { "sty",  0xFF, 0xDF },*/
485
  { "suba", 0xB0, 0x90 },
486
  { "subb", 0xF0, 0xD0 },
487
  { "subd", 0xB3, 0x93 },
488
  { 0, 0, 0 }
489
};
490
 
491
static struct m68hc11_direct_relax *
492
find_relaxable_insn (unsigned char code)
493
{
494
  int i;
495
 
496
  for (i = 0; m68hc11_direct_relax_table[i].name; i++)
497
    if (m68hc11_direct_relax_table[i].code == code)
498
      return &m68hc11_direct_relax_table[i];
499
 
500
  return 0;
501
}
502
 
503
static int
504
compare_reloc (e1, e2)
505
     const void *e1;
506
     const void *e2;
507
{
508
  const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
509
  const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;
510
 
511
  if (i1->r_offset == i2->r_offset)
512
    return 0;
513
  else
514
    return i1->r_offset < i2->r_offset ? -1 : 1;
515
}
516
 
517
#define M6811_OP_LDX_IMMEDIATE (0xCE)
518
 
519
static void
520
m68hc11_relax_group (abfd, sec, contents, value, offset, end_group)
521
     bfd *abfd;
522
     asection *sec;
523
     bfd_byte *contents;
524
     unsigned value;
525
     unsigned long offset;
526
     unsigned long end_group;
527
{
528
  unsigned char code;
529
  unsigned long start_offset;
530
  unsigned long ldx_offset = offset;
531
  unsigned long ldx_size;
532
  int can_delete_ldx;
533
  int relax_ldy = 0;
534
 
535
  /* First instruction of the relax group must be a
536
     LDX #value or LDY #value.  If this is not the case,
537
     ignore the relax group.  */
538
  code = bfd_get_8 (abfd, contents + offset);
539
  if (code == 0x18)
540
    {
541
      relax_ldy++;
542
      offset++;
543
      code = bfd_get_8 (abfd, contents + offset);
544
    }
545
  ldx_size = offset - ldx_offset + 3;
546
  offset += 3;
547
  if (code != M6811_OP_LDX_IMMEDIATE || offset >= end_group)
548
    return;
549
 
550
 
551
  /* We can remove the LDX/LDY only when all bset/brclr instructions
552
     of the relax group have been converted to use direct addressing
553
     mode.  */
554
  can_delete_ldx = 1;
555
  while (offset < end_group)
556
    {
557
      unsigned isize;
558
      unsigned new_value;
559
      int bset_use_y;
560
 
561
      bset_use_y = 0;
562
      start_offset = offset;
563
      code = bfd_get_8 (abfd, contents + offset);
564
      if (code == 0x18)
565
        {
566
          bset_use_y++;
567
          offset++;
568
          code = bfd_get_8 (abfd, contents + offset);
569
        }
570
 
571
      /* Check the instruction and translate to use direct addressing mode.  */
572
      switch (code)
573
        {
574
          /* bset */
575
        case 0x1C:
576
          code = 0x14;
577
          isize = 3;
578
          break;
579
 
580
          /* brclr */
581
        case 0x1F:
582
          code = 0x13;
583
          isize = 4;
584
          break;
585
 
586
          /* brset */
587
        case 0x1E:
588
          code = 0x12;
589
          isize = 4;
590
          break;
591
 
592
          /* bclr */
593
        case 0x1D:
594
          code = 0x15;
595
          isize = 3;
596
          break;
597
 
598
          /* This instruction is not recognized and we are not
599
             at end of the relax group.  Ignore and don't remove
600
             the first LDX (we don't know what it is used for...).  */
601
        default:
602
          return;
603
        }
604
      new_value = (unsigned) bfd_get_8 (abfd, contents + offset + 1);
605
      new_value += value;
606
      if ((new_value & 0xff00) == 0 && bset_use_y == relax_ldy)
607
        {
608
          bfd_put_8 (abfd, code, contents + offset);
609
          bfd_put_8 (abfd, new_value, contents + offset + 1);
610
          if (start_offset != offset)
611
            {
612
              m68hc11_elf_relax_delete_bytes (abfd, sec, start_offset,
613
                                              offset - start_offset);
614
              end_group--;
615
            }
616
        }
617
      else
618
        {
619
          can_delete_ldx = 0;
620
        }
621
      offset = start_offset + isize;
622
    }
623
  if (can_delete_ldx)
624
    {
625
      /* Remove the move instruction (3 or 4 bytes win).  */
626
      m68hc11_elf_relax_delete_bytes (abfd, sec, ldx_offset, ldx_size);
627
    }
628
}
629
 
630
/* This function handles relaxing for the 68HC11.
631
 
632
 
633
        and somewhat more difficult to support.  */
634
 
635
static boolean
636
m68hc11_elf_relax_section (abfd, sec, link_info, again)
637
     bfd *abfd;
638
     asection *sec;
639
     struct bfd_link_info *link_info;
640
     boolean *again;
641
{
642
  Elf_Internal_Shdr *symtab_hdr;
643
  Elf_Internal_Shdr *shndx_hdr;
644
  Elf_Internal_Rela *internal_relocs;
645
  Elf_Internal_Rela *free_relocs = NULL;
646
  Elf_Internal_Rela *irel, *irelend;
647
  bfd_byte *contents = NULL;
648
  bfd_byte *free_contents = NULL;
649
  Elf32_External_Sym *extsyms = NULL;
650
  Elf32_External_Sym *free_extsyms = NULL;
651
  Elf_Internal_Rela *prev_insn_branch = NULL;
652
  Elf_Internal_Rela *prev_insn_group = NULL;
653
  unsigned insn_group_value = 0;
654
  Elf_External_Sym_Shndx *shndx_buf = NULL;
655
 
656
  /* Assume nothing changes.  */
657
  *again = false;
658
 
659
  /* We don't have to do anything for a relocateable link, if
660
     this section does not have relocs, or if this is not a
661
     code section.  */
662
  if (link_info->relocateable
663
      || (sec->flags & SEC_RELOC) == 0
664
      || sec->reloc_count == 0
665
      || (sec->flags & SEC_CODE) == 0)
666
    return true;
667
 
668
  /* If this is the first time we have been called for this section,
669
     initialize the cooked size.  */
670
  if (sec->_cooked_size == 0)
671
    sec->_cooked_size = sec->_raw_size;
672
 
673
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
674
  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
675
 
676
  /* Get a copy of the native relocations.  */
677
  internal_relocs = (_bfd_elf32_link_read_relocs
678
                     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
679
                      link_info->keep_memory));
680
  if (internal_relocs == NULL)
681
    goto error_return;
682
  if (! link_info->keep_memory)
683
    free_relocs = internal_relocs;
684
 
685
  /* Checking for branch relaxation relies on the relocations to
686
     be sorted on 'r_offset'.  This is not guaranteed so we must sort.  */
687
  qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
688
         compare_reloc);
689
 
690
  /* Walk through them looking for relaxing opportunities.  */
691
  irelend = internal_relocs + sec->reloc_count;
692
  for (irel = internal_relocs; irel < irelend; irel++)
693
    {
694
      bfd_vma symval;
695
      bfd_vma value;
696
      Elf_Internal_Sym isym;
697
 
698
      /* If this isn't something that can be relaxed, then ignore
699
         this reloc.  */
700
      if (ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_16
701
          && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_JUMP
702
          && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_GROUP)
703
        {
704
          prev_insn_branch = 0;
705
          prev_insn_group = 0;
706
          continue;
707
        }
708
 
709
      /* Get the section contents if we haven't done so already.  */
710
      if (contents == NULL)
711
        {
712
          /* Get cached copy if it exists.  */
713
          if (elf_section_data (sec)->this_hdr.contents != NULL)
714
            contents = elf_section_data (sec)->this_hdr.contents;
715
          else
716
            {
717
              /* Go get them off disk.  */
718
              contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
719
              if (contents == NULL)
720
                goto error_return;
721
              free_contents = contents;
722
 
723
              if (! bfd_get_section_contents (abfd, sec, contents,
724
                                              (file_ptr) 0, sec->_raw_size))
725
                goto error_return;
726
            }
727
        }
728
 
729
      /* Try to eliminate an unconditional 8 bit pc-relative branch
730
         which immediately follows a conditional 8 bit pc-relative
731
         branch around the unconditional branch.
732
 
733
            original:           new:
734
            bCC lab1            bCC' lab2
735
            bra lab2
736
           lab1:               lab1:
737
 
738
         This happens when the bCC can't reach lab2 at assembly time,
739
         but due to other relaxations it can reach at link time.  */
740
      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_JUMP)
741
        {
742
          Elf_Internal_Rela *nrel;
743
          unsigned char code;
744
          unsigned char roffset;
745
 
746
          prev_insn_branch = 0;
747
          prev_insn_group = 0;
748
 
749
          /* Do nothing if this reloc is the last byte in the section.  */
750
          if (irel->r_offset == sec->_cooked_size)
751
            continue;
752
 
753
          /* See if the next instruction is an unconditional pc-relative
754
             branch, more often than not this test will fail, so we
755
             test it first to speed things up.  */
756
          code = bfd_get_8 (abfd, contents + irel->r_offset + 2);
757
          if (code != 0x7e)
758
            continue;
759
 
760
          /* Also make sure the next relocation applies to the next
761
             instruction and that it's a pc-relative 8 bit branch.  */
762
          nrel = irel + 1;
763
          if (nrel == irelend
764
              || irel->r_offset + 3 != nrel->r_offset
765
              || ELF32_R_TYPE (nrel->r_info) != (int) R_M68HC11_16)
766
            continue;
767
 
768
          /* Make sure our destination immediately follows the
769
             unconditional branch.  */
770
          roffset = bfd_get_8 (abfd, contents + irel->r_offset + 1);
771
          if (roffset != 3)
772
            continue;
773
 
774
          prev_insn_branch = irel;
775
          prev_insn_group = 0;
776
          continue;
777
        }
778
 
779
      /* Read this BFD's symbols if we haven't done so already.  */
780
      if (extsyms == NULL)
781
        {
782
          /* Get cached copy if it exists.  */
783
          if (symtab_hdr->contents != NULL)
784
            extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
785
          else
786
            {
787
              /* Go get them off disk.  */
788
              bfd_size_type amt = symtab_hdr->sh_size;
789
              extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
790
              if (extsyms == NULL)
791
                goto error_return;
792
              free_extsyms = extsyms;
793
              if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
794
                  || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
795
                goto error_return;
796
            }
797
 
798
          if (shndx_hdr->sh_size != 0)
799
            {
800
              bfd_size_type amt;
801
 
802
              amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
803
              shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
804
              if (shndx_buf == NULL)
805
                goto error_return;
806
              if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
807
                  || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
808
                goto error_return;
809
              shndx_hdr->contents = (PTR) shndx_buf;
810
            }
811
        }
812
 
813
      /* Get the value of the symbol referred to by the reloc.  */
814
      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
815
        {
816
          Elf32_External_Sym *esym;
817
          Elf_External_Sym_Shndx *shndx;
818
          asection *sym_sec;
819
 
820
          /* A local symbol.  */
821
          esym = extsyms + ELF32_R_SYM (irel->r_info);
822
          shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0);
823
          bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
824
 
825
          sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);
826
          symval = (isym.st_value
827
                    + sym_sec->output_section->vma
828
                    + sym_sec->output_offset);
829
        }
830
      else
831
        {
832
          unsigned long indx;
833
          struct elf_link_hash_entry *h;
834
 
835
          /* An external symbol.  */
836
          indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
837
          h = elf_sym_hashes (abfd)[indx];
838
          BFD_ASSERT (h != NULL);
839
          if (h->root.type != bfd_link_hash_defined
840
              && h->root.type != bfd_link_hash_defweak)
841
            {
842
              /* This appears to be a reference to an undefined
843
                 symbol.  Just ignore it--it will be caught by the
844
                 regular reloc processing.  */
845
              prev_insn_branch = 0;
846
              prev_insn_group = 0;
847
              continue;
848
            }
849
 
850
          symval = (h->root.u.def.value
851
                    + h->root.u.def.section->output_section->vma
852
                    + h->root.u.def.section->output_offset);
853
        }
854
 
855
      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
856
        {
857
          prev_insn_branch = 0;
858
          prev_insn_group = 0;
859
 
860
          /* Do nothing if this reloc is the last byte in the section.  */
861
          if (irel->r_offset == sec->_cooked_size)
862
            continue;
863
 
864
          prev_insn_group = irel;
865
          insn_group_value = isym.st_value;
866
          continue;
867
        }
868
 
869
      value = symval;
870
      /* Try to turn a far branch to a near branch.  */
871
      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
872
          && prev_insn_branch)
873
        {
874
          bfd_vma offset;
875
          unsigned char code;
876
 
877
          offset = value - (prev_insn_branch->r_offset
878
                            + sec->output_section->vma
879
                            + sec->output_offset + 2);
880
 
881
          /* If the offset is still out of -128..+127 range,
882
             leave that far branch unchanged.  */
883
          if ((offset & 0xff80) != 0 && (offset & 0xff80) != 0xff80)
884
            {
885
              prev_insn_branch = 0;
886
              continue;
887
            }
888
 
889
          /* Shrink the branch.  */
890
          code = bfd_get_8 (abfd, contents + prev_insn_branch->r_offset);
891
          if (code == 0x7e)
892
            {
893
              code = 0x20;
894
              bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
895
              bfd_put_8 (abfd, offset,
896
                         contents + prev_insn_branch->r_offset + 1);
897
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
898
                                           R_M68HC11_NONE);
899
              m68hc11_elf_relax_delete_bytes (abfd, sec,
900
                                              irel->r_offset, 1);
901
            }
902
          else
903
            {
904
              code ^= 0x1;
905
              bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
906
              bfd_put_8 (abfd, offset,
907
                         contents + prev_insn_branch->r_offset + 1);
908
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
909
                                           R_M68HC11_NONE);
910
              m68hc11_elf_relax_delete_bytes (abfd, sec,
911
                                              irel->r_offset - 1, 3);
912
            }
913
          prev_insn_branch = 0;
914
        }
915
 
916
      /* Try to turn a 16 bit address into a 8 bit page0 address.  */
917
      else if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
918
               && (value & 0xff00) == 0)
919
        {
920
          unsigned char code;
921
          unsigned short offset;
922
          struct m68hc11_direct_relax *rinfo;
923
 
924
          prev_insn_branch = 0;
925
          offset = bfd_get_16 (abfd, contents + irel->r_offset);
926
          offset += value;
927
          if ((offset & 0xff00) != 0)
928
            {
929
              prev_insn_group = 0;
930
              continue;
931
            }
932
 
933
          if (prev_insn_group)
934
            {
935
              /* Note that we've changed the reldection contents, etc.  */
936
              elf_section_data (sec)->relocs = internal_relocs;
937
              free_relocs = NULL;
938
 
939
              elf_section_data (sec)->this_hdr.contents = contents;
940
              free_contents = NULL;
941
 
942
              symtab_hdr->contents = (bfd_byte *) extsyms;
943
              free_extsyms = NULL;
944
 
945
              m68hc11_relax_group (abfd, sec, contents, offset,
946
                                   prev_insn_group->r_offset,
947
                                   insn_group_value);
948
              irel = prev_insn_group;
949
              prev_insn_group = 0;
950
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
951
                                           R_M68HC11_NONE);
952
              continue;
953
            }
954
 
955
          /* Get the opcode.  */
956
          code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
957
          rinfo = find_relaxable_insn (code);
958
          if (rinfo == 0)
959
            {
960
              prev_insn_group = 0;
961
              continue;
962
            }
963
 
964
          /* Note that we've changed the reldection contents, etc.  */
965
          elf_section_data (sec)->relocs = internal_relocs;
966
          free_relocs = NULL;
967
 
968
          elf_section_data (sec)->this_hdr.contents = contents;
969
          free_contents = NULL;
970
 
971
          symtab_hdr->contents = (bfd_byte *) extsyms;
972
          free_extsyms = NULL;
973
 
974
          /* Fix the opcode.  */
975
          /* printf ("A relaxable case : 0x%02x (%s)\n",
976
             code, rinfo->name); */
977
          bfd_put_8 (abfd, rinfo->direct_code,
978
                     contents + irel->r_offset - 1);
979
 
980
          /* Delete one byte of data (upper byte of address).  */
981
          m68hc11_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 1);
982
 
983
          /* Fix the relocation's type.  */
984
          irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
985
                                       R_M68HC11_8);
986
 
987
          /* That will change things, so, we should relax again.
988
             Note that this is not required, and it may be slow.  */
989
          *again = true;
990
        }
991
      else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16)
992
        {
993
          unsigned char code;
994
          bfd_vma offset;
995
 
996
          prev_insn_branch = 0;
997
          code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
998
          if (code == 0x7e)
999
            {
1000
              offset = value - (irel->r_offset
1001
                                + sec->output_section->vma
1002
                                + sec->output_offset + 1);
1003
              offset += bfd_get_16 (abfd, contents + irel->r_offset);
1004
 
1005
              /* If the offset is still out of -128..+127 range,
1006
                 leave that far branch unchanged.  */
1007
              if ((offset & 0xff80) == 0 || (offset & 0xff80) == 0xff80)
1008
                {
1009
 
1010
                  /* Note that we've changed the reldection contents, etc.  */
1011
                  elf_section_data (sec)->relocs = internal_relocs;
1012
                  free_relocs = NULL;
1013
 
1014
                  elf_section_data (sec)->this_hdr.contents = contents;
1015
                  free_contents = NULL;
1016
 
1017
                  symtab_hdr->contents = (bfd_byte *) extsyms;
1018
                  free_extsyms = NULL;
1019
 
1020
                  /* Shrink the branch.  */
1021
                  code = 0x20;
1022
                  bfd_put_8 (abfd, code,
1023
                             contents + irel->r_offset - 1);
1024
                  bfd_put_8 (abfd, offset,
1025
                             contents + irel->r_offset);
1026
                  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1027
                                               R_M68HC11_NONE);
1028
                  m68hc11_elf_relax_delete_bytes (abfd, sec,
1029
                                                  irel->r_offset + 1, 1);
1030
                }
1031
            }
1032
        }
1033
      prev_insn_branch = 0;
1034
    }
1035
 
1036
  if (free_relocs != NULL)
1037
    {
1038
      free (free_relocs);
1039
      free_relocs = NULL;
1040
    }
1041
 
1042
  if (free_contents != NULL)
1043
    {
1044
      if (! link_info->keep_memory)
1045
        free (free_contents);
1046
      else
1047
        {
1048
          /* Cache the section contents for elf_link_input_bfd.  */
1049
          elf_section_data (sec)->this_hdr.contents = contents;
1050
        }
1051
      free_contents = NULL;
1052
    }
1053
 
1054
  if (free_extsyms != NULL)
1055
    {
1056
      if (! link_info->keep_memory)
1057
        free (free_extsyms);
1058
      else
1059
        {
1060
          /* Cache the symbols for elf_link_input_bfd.  */
1061
          symtab_hdr->contents = (unsigned char *) extsyms;
1062
        }
1063
      free_extsyms = NULL;
1064
    }
1065
 
1066
  return true;
1067
 
1068
 error_return:
1069
  if (free_relocs != NULL)
1070
    free (free_relocs);
1071
  if (free_contents != NULL)
1072
    free (free_contents);
1073
  if (free_extsyms != NULL)
1074
    free (free_extsyms);
1075
  return false;
1076
}
1077
 
1078
/* Delete some bytes from a section while relaxing.  */
1079
 
1080
static void
1081
m68hc11_elf_relax_delete_bytes (abfd, sec, addr, count)
1082
     bfd *abfd;
1083
     asection *sec;
1084
     bfd_vma addr;
1085
     int count;
1086
{
1087
  Elf_Internal_Shdr *symtab_hdr;
1088
  Elf_Internal_Shdr *shndx_hdr;
1089
  Elf32_External_Sym *extsyms;
1090
  unsigned int sec_shndx;
1091
  Elf_External_Sym_Shndx *shndx;
1092
  bfd_byte *contents;
1093
  Elf_Internal_Rela *irel, *irelend;
1094
  bfd_vma toaddr;
1095
  Elf32_External_Sym *esym, *esymend;
1096
  struct elf_link_hash_entry **sym_hashes;
1097
  struct elf_link_hash_entry **end_hashes;
1098
  unsigned int symcount;
1099
 
1100
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1101
  extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
1102
 
1103
  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1104
 
1105
  contents = elf_section_data (sec)->this_hdr.contents;
1106
 
1107
  toaddr = sec->_cooked_size;
1108
 
1109
  irel = elf_section_data (sec)->relocs;
1110
  irelend = irel + sec->reloc_count;
1111
 
1112
  /* Actually delete the bytes.  */
1113
  memmove (contents + addr, contents + addr + count,
1114
           (size_t) (toaddr - addr - count));
1115
  sec->_cooked_size -= count;
1116
 
1117
  /* Adjust all the relocs.  */
1118
  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1119
    {
1120
      unsigned char code;
1121
      unsigned char offset;
1122
      unsigned short raddr;
1123
      unsigned long old_offset;
1124
      int branch_pos;
1125
 
1126
      old_offset = irel->r_offset;
1127
 
1128
      /* See if this reloc was for the bytes we have deleted, in which
1129
         case we no longer care about it.  Don't delete relocs which
1130
         represent addresses, though.  */
1131
      if (ELF32_R_TYPE (irel->r_info) != R_M68HC11_RL_JUMP
1132
          && irel->r_offset >= addr && irel->r_offset < addr + count)
1133
        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1134
                                     R_M68HC11_NONE);
1135
 
1136
      if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_NONE)
1137
        continue;
1138
 
1139
      /* Get the new reloc address.  */
1140
      if ((irel->r_offset > addr
1141
           && irel->r_offset < toaddr))
1142
        irel->r_offset -= count;
1143
 
1144
      /* If this is a PC relative reloc, see if the range it covers
1145
         includes the bytes we have deleted.  */
1146
      switch (ELF32_R_TYPE (irel->r_info))
1147
        {
1148
        default:
1149
          break;
1150
 
1151
        case R_M68HC11_RL_JUMP:
1152
          code = bfd_get_8 (abfd, contents + irel->r_offset);
1153
          switch (code)
1154
            {
1155
              /* jsr and jmp instruction are also marked with RL_JUMP
1156
                 relocs but no adjustment must be made.  */
1157
            case 0x7e:
1158
            case 0x9d:
1159
            case 0xbd:
1160
              continue;
1161
 
1162
            case 0x12:
1163
            case 0x13:
1164
              branch_pos = 3;
1165
              raddr = 4;
1166
 
1167
              /* Special case when we translate a brclr N,y into brclr *<addr>
1168
                 In this case, the 0x18 page2 prefix is removed.
1169
                 The reloc offset is not modified but the instruction
1170
                 size is reduced by 1.  */
1171
              if (old_offset == addr)
1172
                raddr++;
1173
              break;
1174
 
1175
            case 0x1e:
1176
            case 0x1f:
1177
              branch_pos = 3;
1178
              raddr = 4;
1179
              break;
1180
 
1181
            case 0x18:
1182
              branch_pos = 4;
1183
              raddr = 5;
1184
              break;
1185
 
1186
            default:
1187
              branch_pos = 1;
1188
              raddr = 2;
1189
              break;
1190
            }
1191
          offset = bfd_get_8 (abfd, contents + irel->r_offset + branch_pos);
1192
          raddr += old_offset;
1193
          raddr += ((unsigned short) offset | ((offset & 0x80) ? 0xff00 : 0));
1194
          if (irel->r_offset < addr && raddr >= addr)
1195
            {
1196
              offset -= count;
1197
              bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
1198
            }
1199
          else if (irel->r_offset >= addr && raddr <= addr)
1200
            {
1201
              offset += count;
1202
              bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
1203
            }
1204
          else
1205
            {
1206
              /*printf ("Not adjusted 0x%04x [0x%4x 0x%4x]\n", raddr,
1207
                irel->r_offset, addr);*/
1208
            }
1209
 
1210
          break;
1211
        }
1212
    }
1213
 
1214
  /* Adjust the local symbols defined in this section.  */
1215
  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
1216
  shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
1217
  esym = extsyms;
1218
  esymend = esym + symtab_hdr->sh_info;
1219
  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
1220
    {
1221
      Elf_Internal_Sym isym;
1222
      Elf_External_Sym_Shndx dummy;
1223
 
1224
      bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
1225
 
1226
      if (isym.st_shndx == sec_shndx
1227
          && isym.st_value > addr
1228
          && isym.st_value < toaddr)
1229
        {
1230
          isym.st_value -= count;
1231
          bfd_elf32_swap_symbol_out (abfd, &isym, esym, &dummy);
1232
        }
1233
    }
1234
 
1235
  /* Now adjust the global symbols defined in this section.  */
1236
  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1237
              - symtab_hdr->sh_info);
1238
  sym_hashes = elf_sym_hashes (abfd);
1239
  end_hashes = sym_hashes + symcount;
1240
  for (; sym_hashes < end_hashes; sym_hashes++)
1241
    {
1242
      struct elf_link_hash_entry *sym_hash = *sym_hashes;
1243
      if ((sym_hash->root.type == bfd_link_hash_defined
1244
           || sym_hash->root.type == bfd_link_hash_defweak)
1245
          && sym_hash->root.u.def.section == sec
1246
          && sym_hash->root.u.def.value > addr
1247
          && sym_hash->root.u.def.value < toaddr)
1248
        {
1249
          sym_hash->root.u.def.value -= count;
1250
        }
1251
    }
1252
}
1253
 
1254
/* Look through the relocs for a section during the first phase.
1255
   Since we don't do .gots or .plts, we just need to consider the
1256
   virtual table relocs for gc.  */
1257
 
1258
static boolean
1259
elf32_m68hc11_check_relocs (abfd, info, sec, relocs)
1260
     bfd * abfd;
1261
     struct bfd_link_info * info;
1262
     asection * sec;
1263
     const Elf_Internal_Rela * relocs;
1264
{
1265
  Elf_Internal_Shdr *           symtab_hdr;
1266
  struct elf_link_hash_entry ** sym_hashes;
1267
  struct elf_link_hash_entry ** sym_hashes_end;
1268
  const Elf_Internal_Rela *     rel;
1269
  const Elf_Internal_Rela *     rel_end;
1270
 
1271
  if (info->relocateable)
1272
    return true;
1273
 
1274
  symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1275
  sym_hashes = elf_sym_hashes (abfd);
1276
  sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
1277
  if (!elf_bad_symtab (abfd))
1278
    sym_hashes_end -= symtab_hdr->sh_info;
1279
 
1280
  rel_end = relocs + sec->reloc_count;
1281
 
1282
  for (rel = relocs; rel < rel_end; rel++)
1283
    {
1284
      struct elf_link_hash_entry * h;
1285
      unsigned long r_symndx;
1286
 
1287
      r_symndx = ELF32_R_SYM (rel->r_info);
1288
 
1289
      if (r_symndx < symtab_hdr->sh_info)
1290
        h = NULL;
1291
      else
1292
        h = sym_hashes [r_symndx - symtab_hdr->sh_info];
1293
 
1294
      switch (ELF32_R_TYPE (rel->r_info))
1295
        {
1296
        /* This relocation describes the C++ object vtable hierarchy.
1297
           Reconstruct it for later use during GC.  */
1298
        case R_M68HC11_GNU_VTINHERIT:
1299
          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
1300
            return false;
1301
          break;
1302
 
1303
        /* This relocation describes which C++ vtable entries are actually
1304
           used.  Record for later use during GC.  */
1305
        case R_M68HC11_GNU_VTENTRY:
1306
          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
1307
            return false;
1308
          break;
1309
        }
1310
    }
1311
 
1312
  return true;
1313
}
1314
 
1315
/* Relocate a 68hc11/68hc12 ELF section.  */
1316
static boolean
1317
elf32_m68hc11_relocate_section (output_bfd, info, input_bfd, input_section,
1318
                                contents, relocs, local_syms, local_sections)
1319
     bfd *output_bfd ATTRIBUTE_UNUSED;
1320
     struct bfd_link_info *info;
1321
     bfd *input_bfd;
1322
     asection *input_section;
1323
     bfd_byte *contents;
1324
     Elf_Internal_Rela *relocs;
1325
     Elf_Internal_Sym *local_syms;
1326
     asection **local_sections;
1327
{
1328
  Elf_Internal_Shdr *symtab_hdr;
1329
  struct elf_link_hash_entry **sym_hashes;
1330
  Elf_Internal_Rela *rel, *relend;
1331
  const char *name;
1332
 
1333
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1334
  sym_hashes = elf_sym_hashes (input_bfd);
1335
 
1336
  rel = relocs;
1337
  relend = relocs + input_section->reloc_count;
1338
  for (; rel < relend; rel++)
1339
    {
1340
      int r_type;
1341
      reloc_howto_type *howto;
1342
      unsigned long r_symndx;
1343
      Elf_Internal_Sym *sym;
1344
      asection *sec;
1345
      struct elf_link_hash_entry *h;
1346
      bfd_vma relocation;
1347
      bfd_reloc_status_type r;
1348
 
1349
      r_symndx = ELF32_R_SYM (rel->r_info);
1350
      r_type = ELF32_R_TYPE (rel->r_info);
1351
 
1352
      if (r_type == R_M68HC11_GNU_VTENTRY
1353
          || r_type == R_M68HC11_GNU_VTINHERIT )
1354
        continue;
1355
 
1356
      howto = elf_m68hc11_howto_table + r_type;
1357
 
1358
      if (info->relocateable)
1359
        {
1360
          /* This is a relocateable link.  We don't have to change
1361
             anything, unless the reloc is against a section symbol,
1362
             in which case we have to adjust according to where the
1363
             section symbol winds up in the output section.  */
1364
          if (r_symndx < symtab_hdr->sh_info)
1365
            {
1366
              sym = local_syms + r_symndx;
1367
              if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1368
                {
1369
                  sec = local_sections[r_symndx];
1370
                  rel->r_addend += sec->output_offset + sym->st_value;
1371
                }
1372
            }
1373
 
1374
          continue;
1375
        }
1376
 
1377
      /* This is a final link.  */
1378
      h = NULL;
1379
      sym = NULL;
1380
      sec = NULL;
1381
      if (r_symndx < symtab_hdr->sh_info)
1382
        {
1383
          sym = local_syms + r_symndx;
1384
          sec = local_sections[r_symndx];
1385
          relocation = (sec->output_section->vma
1386
                        + sec->output_offset
1387
                        + sym->st_value);
1388
        }
1389
      else
1390
        {
1391
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1392
          while (h->root.type == bfd_link_hash_indirect
1393
                 || h->root.type == bfd_link_hash_warning)
1394
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
1395
          if (h->root.type == bfd_link_hash_defined
1396
              || h->root.type == bfd_link_hash_defweak)
1397
            {
1398
              sec = h->root.u.def.section;
1399
              relocation = (h->root.u.def.value
1400
                            + sec->output_section->vma
1401
                            + sec->output_offset);
1402
            }
1403
          else if (h->root.type == bfd_link_hash_undefweak)
1404
            relocation = 0;
1405
          else
1406
            {
1407
              if (!((*info->callbacks->undefined_symbol)
1408
                    (info, h->root.root.string, input_bfd,
1409
                     input_section, rel->r_offset, true)))
1410
                return false;
1411
              relocation = 0;
1412
            }
1413
        }
1414
 
1415
      if (h != NULL)
1416
        name = h->root.root.string;
1417
      else
1418
        {
1419
          name = (bfd_elf_string_from_elf_section
1420
                  (input_bfd, symtab_hdr->sh_link, sym->st_name));
1421
          if (name == NULL || *name == '\0')
1422
            name = bfd_section_name (input_bfd, sec);
1423
        }
1424
 
1425
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
1426
                                    contents, rel->r_offset,
1427
                                    relocation, rel->r_addend);
1428
 
1429
      if (r != bfd_reloc_ok)
1430
        {
1431
          const char * msg = (const char *) 0;
1432
 
1433
          switch (r)
1434
            {
1435
            case bfd_reloc_overflow:
1436
              if (!((*info->callbacks->reloc_overflow)
1437
                    (info, name, howto->name, (bfd_vma) 0,
1438
                     input_bfd, input_section, rel->r_offset)))
1439
                return false;
1440
              break;
1441
 
1442
            case bfd_reloc_undefined:
1443
              if (!((*info->callbacks->undefined_symbol)
1444
                    (info, name, input_bfd, input_section,
1445
                     rel->r_offset, true)))
1446
                return false;
1447
              break;
1448
 
1449
            case bfd_reloc_outofrange:
1450
              msg = _ ("internal error: out of range error");
1451
              goto common_error;
1452
 
1453
            case bfd_reloc_notsupported:
1454
              msg = _ ("internal error: unsupported relocation error");
1455
              goto common_error;
1456
 
1457
            case bfd_reloc_dangerous:
1458
              msg = _ ("internal error: dangerous error");
1459
              goto common_error;
1460
 
1461
            default:
1462
              msg = _ ("internal error: unknown error");
1463
              /* fall through */
1464
 
1465
            common_error:
1466
              if (!((*info->callbacks->warning)
1467
                    (info, msg, name, input_bfd, input_section,
1468
                     rel->r_offset)))
1469
                return false;
1470
              break;
1471
            }
1472
        }
1473
    }
1474
 
1475
  return true;
1476
}
1477
 
1478
 
1479
 
1480
/* Set and control ELF flags in ELF header.  */
1481
 
1482
boolean
1483
_bfd_m68hc11_elf_set_private_flags (abfd, flags)
1484
     bfd *abfd;
1485
     flagword flags;
1486
{
1487
  BFD_ASSERT (!elf_flags_init (abfd)
1488
              || elf_elfheader (abfd)->e_flags == flags);
1489
 
1490
  elf_elfheader (abfd)->e_flags = flags;
1491
  elf_flags_init (abfd) = true;
1492
  return true;
1493
}
1494
 
1495
/* Merge backend specific data from an object file to the output
1496
   object file when linking.  */
1497
 
1498
boolean
1499
_bfd_m68hc11_elf_merge_private_bfd_data (ibfd, obfd)
1500
     bfd *ibfd;
1501
     bfd *obfd;
1502
{
1503
  flagword old_flags;
1504
  flagword new_flags;
1505
  boolean ok = true;
1506
 
1507
  /* Check if we have the same endianess */
1508
  if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
1509
    return false;
1510
 
1511
  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1512
      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1513
    return true;
1514
 
1515
  new_flags = elf_elfheader (ibfd)->e_flags;
1516
  elf_elfheader (obfd)->e_flags |= new_flags & EF_M68HC11_ABI;
1517
  old_flags = elf_elfheader (obfd)->e_flags;
1518
 
1519
  if (! elf_flags_init (obfd))
1520
    {
1521
      elf_flags_init (obfd) = true;
1522
      elf_elfheader (obfd)->e_flags = new_flags;
1523
      elf_elfheader (obfd)->e_ident[EI_CLASS]
1524
        = elf_elfheader (ibfd)->e_ident[EI_CLASS];
1525
 
1526
      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
1527
          && bfd_get_arch_info (obfd)->the_default)
1528
        {
1529
          if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
1530
                                   bfd_get_mach (ibfd)))
1531
            return false;
1532
        }
1533
 
1534
      return true;
1535
    }
1536
 
1537
  /* Check ABI compatibility.  */
1538
  if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
1539
    {
1540
      (*_bfd_error_handler)
1541
        (_("%s: linking files compiled for 16-bit integers (-mshort) "
1542
           "and others for 32-bit integers"),
1543
         bfd_archive_filename (ibfd));
1544
      ok = false;
1545
    }
1546
  if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
1547
    {
1548
      (*_bfd_error_handler)
1549
        (_("%s: linking files compiled for 32-bit double (-fshort-double) "
1550
           "and others for 64-bit double"),
1551
         bfd_archive_filename (ibfd));
1552
      ok = false;
1553
    }
1554
  new_flags &= ~EF_M68HC11_ABI;
1555
  old_flags &= ~EF_M68HC11_ABI;
1556
 
1557
  /* Warn about any other mismatches */
1558
  if (new_flags != old_flags)
1559
    {
1560
      (*_bfd_error_handler)
1561
        (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
1562
         bfd_archive_filename (ibfd), (unsigned long) new_flags,
1563
         (unsigned long) old_flags);
1564
      ok = false;
1565
    }
1566
 
1567
  if (! ok)
1568
    {
1569
      bfd_set_error (bfd_error_bad_value);
1570
      return false;
1571
    }
1572
 
1573
  return true;
1574
}
1575
 
1576
boolean
1577
_bfd_m68hc11_elf_print_private_bfd_data (abfd, ptr)
1578
     bfd *abfd;
1579
     PTR ptr;
1580
{
1581
  FILE *file = (FILE *) ptr;
1582
 
1583
  BFD_ASSERT (abfd != NULL && ptr != NULL);
1584
 
1585
  /* Print normal ELF private data.  */
1586
  _bfd_elf_print_private_bfd_data (abfd, ptr);
1587
 
1588
  /* xgettext:c-format */
1589
  fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
1590
 
1591
  if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
1592
    fprintf (file, _("[abi=32-bit int,"));
1593
  else
1594
    fprintf (file, _("[abi=16-bit int,"));
1595
 
1596
  if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
1597
    fprintf (file, _(" 64-bit double]"));
1598
  else
1599
    fprintf (file, _(" 32-bit double]"));
1600
 
1601
  if (elf_elfheader (abfd)->e_flags & E_M68HC12_BANKS)
1602
    fprintf (file, _(" [memory=bank-model]"));
1603
  else
1604
    fprintf (file, _(" [memory=flat]"));
1605
 
1606
  fputc ('\n', file);
1607
 
1608
  return true;
1609
}
1610
 
1611
/* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
1612
   The Motorola spec says to use a different Elf machine code.  */
1613
#define ELF_ARCH                bfd_arch_m68hc11
1614
#define ELF_MACHINE_CODE        EM_68HC11
1615
#define ELF_MAXPAGESIZE         0x1000
1616
 
1617
#define TARGET_BIG_SYM          bfd_elf32_m68hc11_vec
1618
#define TARGET_BIG_NAME         "elf32-m68hc11"
1619
 
1620
#define elf_info_to_howto       0
1621
#define elf_info_to_howto_rel   m68hc11_info_to_howto_rel
1622
#define bfd_elf32_bfd_relax_section  m68hc11_elf_relax_section
1623
#define elf_backend_gc_mark_hook     elf32_m68hc11_gc_mark_hook
1624
#define elf_backend_gc_sweep_hook    elf32_m68hc11_gc_sweep_hook
1625
#define elf_backend_check_relocs     elf32_m68hc11_check_relocs
1626
#define elf_backend_relocate_section elf32_m68hc11_relocate_section
1627
#define elf_backend_object_p    0
1628
#define elf_backend_final_write_processing      0
1629
#define elf_backend_can_gc_sections             1
1630
#define bfd_elf32_bfd_merge_private_bfd_data \
1631
                                        _bfd_m68hc11_elf_merge_private_bfd_data
1632
#define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
1633
#define bfd_elf32_bfd_print_private_bfd_data \
1634
                                        _bfd_m68hc11_elf_print_private_bfd_data
1635
 
1636
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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