Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/elf32-m68hc11.c
Line
Count
Source (jump to first uncovered line)
1
/* Motorola 68HC11-specific support for 32-bit ELF
2
   Copyright (C) 1999-2025 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
23
#include "sysdep.h"
24
#include "bfd.h"
25
#include "bfdlink.h"
26
#include "libbfd.h"
27
#include "elf-bfd.h"
28
#include "elf32-m68hc1x.h"
29
#include "elf/m68hc11.h"
30
#include "opcode/m68hc11.h"
31
32
/* Relocation functions.  */
33
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
34
  (bfd *, bfd_reloc_code_real_type);
35
static bool m68hc11_info_to_howto_rel
36
  (bfd *, arelent *, Elf_Internal_Rela *);
37
38
/* Trampoline generation.  */
39
static bool m68hc11_elf_size_one_stub
40
  (struct bfd_hash_entry *gen_entry, void *in_arg);
41
static bool m68hc11_elf_build_one_stub
42
  (struct bfd_hash_entry *gen_entry, void *in_arg);
43
static struct bfd_link_hash_table* m68hc11_elf_bfd_link_hash_table_create
44
  (bfd* abfd);
45
46
/* Linker relaxation.  */
47
static bool m68hc11_elf_relax_section
48
  (bfd *, asection *, struct bfd_link_info *, bool *);
49
static void m68hc11_elf_relax_delete_bytes
50
  (bfd *, asection *, bfd_vma, int);
51
static void m68hc11_relax_group
52
  (bfd *, asection *, bfd_byte *, unsigned, unsigned long, unsigned long);
53
static int compare_reloc (const void *, const void *);
54
55
/* Use REL instead of RELA to save space */
56
#define USE_REL 1
57
58
/* The Motorola 68HC11 microcontroller only addresses 64Kb but we also
59
   support a memory bank switching mechanism similar to 68HC12.
60
   We must handle 8 and 16-bit relocations.  The 32-bit relocation
61
   are used for debugging sections (DWARF2) to represent a virtual
62
   address.
63
   The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
64
static reloc_howto_type elf_m68hc11_howto_table[] = {
65
  /* This reloc does nothing.  */
66
  HOWTO (R_M68HC11_NONE,  /* type */
67
   0,     /* rightshift */
68
   0,     /* size */
69
   0,     /* bitsize */
70
   false,     /* pc_relative */
71
   0,     /* bitpos */
72
   complain_overflow_dont,/* complain_on_overflow */
73
   bfd_elf_generic_reloc, /* special_function */
74
   "R_M68HC11_NONE",  /* name */
75
   false,     /* partial_inplace */
76
   0,     /* src_mask */
77
   0,     /* dst_mask */
78
   false),    /* pcrel_offset */
79
80
  /* A 8 bit absolute relocation */
81
  HOWTO (R_M68HC11_8,   /* type */
82
   0,     /* rightshift */
83
   1,     /* size */
84
   8,     /* bitsize */
85
   false,     /* pc_relative */
86
   0,     /* bitpos */
87
   complain_overflow_bitfield,  /* complain_on_overflow */
88
   bfd_elf_generic_reloc, /* special_function */
89
   "R_M68HC11_8",   /* name */
90
   false,     /* partial_inplace */
91
   0x00ff,    /* src_mask */
92
   0x00ff,    /* dst_mask */
93
   false),    /* pcrel_offset */
94
95
  /* A 8 bit absolute relocation (upper address) */
96
  HOWTO (R_M68HC11_HI8,   /* type */
97
   8,     /* rightshift */
98
   1,     /* size */
99
   8,     /* bitsize */
100
   false,     /* pc_relative */
101
   0,     /* bitpos */
102
   complain_overflow_bitfield,  /* complain_on_overflow */
103
   bfd_elf_generic_reloc, /* special_function */
104
   "R_M68HC11_HI8", /* name */
105
   false,     /* partial_inplace */
106
   0x00ff,    /* src_mask */
107
   0x00ff,    /* dst_mask */
108
   false),    /* pcrel_offset */
109
110
  /* A 8 bit absolute relocation (upper address) */
111
  HOWTO (R_M68HC11_LO8,   /* type */
112
   0,     /* rightshift */
113
   1,     /* size */
114
   8,     /* bitsize */
115
   false,     /* pc_relative */
116
   0,     /* bitpos */
117
   complain_overflow_dont,  /* complain_on_overflow */
118
   bfd_elf_generic_reloc, /* special_function */
119
   "R_M68HC11_LO8", /* name */
120
   false,     /* partial_inplace */
121
   0x00ff,    /* src_mask */
122
   0x00ff,    /* dst_mask */
123
   false),    /* pcrel_offset */
124
125
  /* A 8 bit PC-rel relocation */
126
  HOWTO (R_M68HC11_PCREL_8, /* type */
127
   0,     /* rightshift */
128
   1,     /* size */
129
   8,     /* bitsize */
130
   true,      /* pc_relative */
131
   0,     /* bitpos */
132
   complain_overflow_bitfield,  /* complain_on_overflow */
133
   bfd_elf_generic_reloc, /* special_function */
134
   "R_M68HC11_PCREL_8", /* name */
135
   false,     /* partial_inplace */
136
   0x00ff,    /* src_mask */
137
   0x00ff,    /* dst_mask */
138
   true),     /* pcrel_offset */
139
140
  /* A 16 bit absolute relocation */
141
  HOWTO (R_M68HC11_16,    /* type */
142
   0,     /* rightshift */
143
   2,     /* size */
144
   16,      /* bitsize */
145
   false,     /* pc_relative */
146
   0,     /* bitpos */
147
   complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
148
   bfd_elf_generic_reloc, /* special_function */
149
   "R_M68HC11_16",  /* name */
150
   false,     /* partial_inplace */
151
   0xffff,    /* src_mask */
152
   0xffff,    /* dst_mask */
153
   false),    /* pcrel_offset */
154
155
  /* A 32 bit absolute relocation.  This one is never used for the
156
     code relocation.  It's used by gas for -gstabs generation.  */
157
  HOWTO (R_M68HC11_32,    /* type */
158
   0,     /* rightshift */
159
   4,     /* size */
160
   32,      /* bitsize */
161
   false,     /* pc_relative */
162
   0,     /* bitpos */
163
   complain_overflow_bitfield,  /* complain_on_overflow */
164
   bfd_elf_generic_reloc, /* special_function */
165
   "R_M68HC11_32",  /* name */
166
   false,     /* partial_inplace */
167
   0xffffffff,    /* src_mask */
168
   0xffffffff,    /* dst_mask */
169
   false),    /* pcrel_offset */
170
171
  /* A 3 bit absolute relocation */
172
  HOWTO (R_M68HC11_3B,    /* type */
173
   0,     /* rightshift */
174
   1,     /* size */
175
   3,     /* bitsize */
176
   false,     /* pc_relative */
177
   0,     /* bitpos */
178
   complain_overflow_bitfield,  /* complain_on_overflow */
179
   bfd_elf_generic_reloc, /* special_function */
180
   "R_M68HC11_4B",  /* name */
181
   false,     /* partial_inplace */
182
   0x003,     /* src_mask */
183
   0x003,     /* dst_mask */
184
   false),    /* pcrel_offset */
185
186
  /* A 16 bit PC-rel relocation */
187
  HOWTO (R_M68HC11_PCREL_16,  /* type */
188
   0,     /* rightshift */
189
   2,     /* size */
190
   16,      /* bitsize */
191
   true,      /* pc_relative */
192
   0,     /* bitpos */
193
   complain_overflow_dont,  /* complain_on_overflow */
194
   bfd_elf_generic_reloc, /* special_function */
195
   "R_M68HC11_PCREL_16",  /* name */
196
   false,     /* partial_inplace */
197
   0xffff,    /* src_mask */
198
   0xffff,    /* dst_mask */
199
   true),     /* pcrel_offset */
200
201
  /* GNU extension to record C++ vtable hierarchy */
202
  HOWTO (R_M68HC11_GNU_VTINHERIT, /* type */
203
   0,     /* rightshift */
204
   2,     /* size */
205
   0,     /* bitsize */
206
   false,     /* pc_relative */
207
   0,     /* bitpos */
208
   complain_overflow_dont,  /* complain_on_overflow */
209
   NULL,      /* special_function */
210
   "R_M68HC11_GNU_VTINHERIT", /* name */
211
   false,     /* partial_inplace */
212
   0,     /* src_mask */
213
   0,     /* dst_mask */
214
   false),    /* pcrel_offset */
215
216
  /* GNU extension to record C++ vtable member usage */
217
  HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
218
   0,     /* rightshift */
219
   2,     /* size */
220
   0,     /* bitsize */
221
   false,     /* pc_relative */
222
   0,     /* bitpos */
223
   complain_overflow_dont,  /* complain_on_overflow */
224
   _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
225
   "R_M68HC11_GNU_VTENTRY", /* name */
226
   false,     /* partial_inplace */
227
   0,     /* src_mask */
228
   0,     /* dst_mask */
229
   false),    /* pcrel_offset */
230
231
  /* A 24 bit relocation */
232
  HOWTO (R_M68HC11_24,    /* type */
233
   0,     /* rightshift */
234
   2,     /* size */
235
   24,      /* bitsize */
236
   false,     /* pc_relative */
237
   0,     /* bitpos */
238
   complain_overflow_bitfield,  /* complain_on_overflow */
239
   bfd_elf_generic_reloc, /* special_function */
240
   "R_M68HC11_24",  /* name */
241
   false,     /* partial_inplace */
242
   0xffffff,    /* src_mask */
243
   0xffffff,    /* dst_mask */
244
   false),    /* pcrel_offset */
245
246
  /* A 16-bit low relocation */
247
  HOWTO (R_M68HC11_LO16,  /* type */
248
   0,     /* rightshift */
249
   2,     /* size */
250
   16,      /* bitsize */
251
   false,     /* pc_relative */
252
   0,     /* bitpos */
253
   complain_overflow_bitfield,  /* complain_on_overflow */
254
   bfd_elf_generic_reloc, /* special_function */
255
   "R_M68HC11_LO16",  /* name */
256
   false,     /* partial_inplace */
257
   0xffff,    /* src_mask */
258
   0xffff,    /* dst_mask */
259
   false),    /* pcrel_offset */
260
261
  /* A page relocation */
262
  HOWTO (R_M68HC11_PAGE,  /* type */
263
   0,     /* rightshift */
264
   1,     /* size */
265
   8,     /* bitsize */
266
   false,     /* pc_relative */
267
   0,     /* bitpos */
268
   complain_overflow_bitfield,  /* complain_on_overflow */
269
   bfd_elf_generic_reloc, /* special_function */
270
   "R_M68HC11_PAGE",  /* name */
271
   false,     /* partial_inplace */
272
   0x00ff,    /* src_mask */
273
   0x00ff,    /* dst_mask */
274
   false),    /* pcrel_offset */
275
276
  EMPTY_HOWTO (14),
277
  EMPTY_HOWTO (15),
278
  EMPTY_HOWTO (16),
279
  EMPTY_HOWTO (17),
280
  EMPTY_HOWTO (18),
281
  EMPTY_HOWTO (19),
282
283
  /* Mark beginning of a jump instruction (any form).  */
284
  HOWTO (R_M68HC11_RL_JUMP, /* type */
285
   0,     /* rightshift */
286
   2,     /* size */
287
   0,     /* bitsize */
288
   false,     /* pc_relative */
289
   0,     /* bitpos */
290
   complain_overflow_dont,  /* complain_on_overflow */
291
   m68hc11_elf_ignore_reloc,  /* special_function */
292
   "R_M68HC11_RL_JUMP", /* name */
293
   true,      /* partial_inplace */
294
   0,     /* src_mask */
295
   0,     /* dst_mask */
296
   true),     /* pcrel_offset */
297
298
  /* Mark beginning of Gcc relaxation group instruction.  */
299
  HOWTO (R_M68HC11_RL_GROUP,  /* type */
300
   0,     /* rightshift */
301
   2,     /* size */
302
   0,     /* bitsize */
303
   false,     /* pc_relative */
304
   0,     /* bitpos */
305
   complain_overflow_dont,  /* complain_on_overflow */
306
   m68hc11_elf_ignore_reloc,  /* special_function */
307
   "R_M68HC11_RL_GROUP",  /* name */
308
   true,      /* partial_inplace */
309
   0,     /* src_mask */
310
   0,     /* dst_mask */
311
   true),     /* pcrel_offset */
312
};
313
314
/* Map BFD reloc types to M68HC11 ELF reloc types.  */
315
316
struct m68hc11_reloc_map
317
{
318
  bfd_reloc_code_real_type bfd_reloc_val;
319
  unsigned char elf_reloc_val;
320
};
321
322
static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
323
  {BFD_RELOC_NONE, R_M68HC11_NONE,},
324
  {BFD_RELOC_8, R_M68HC11_8},
325
  {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
326
  {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
327
  {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
328
  {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
329
  {BFD_RELOC_16, R_M68HC11_16},
330
  {BFD_RELOC_32, R_M68HC11_32},
331
  {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
332
333
  {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
334
  {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
335
336
  {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
337
  {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
338
  {BFD_RELOC_M68HC11_24, R_M68HC11_24},
339
340
  {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
341
  {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
342
};
343
344
static reloc_howto_type *
345
bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
346
         bfd_reloc_code_real_type code)
347
0
{
348
0
  unsigned int i;
349
350
0
  for (i = 0;
351
0
       i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
352
0
       i++)
353
0
    {
354
0
      if (m68hc11_reloc_map[i].bfd_reloc_val == code)
355
0
  return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
356
0
    }
357
358
0
  return NULL;
359
0
}
360
361
static reloc_howto_type *
362
bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
363
         const char *r_name)
364
0
{
365
0
  unsigned int i;
366
367
0
  for (i = 0;
368
0
       i < (sizeof (elf_m68hc11_howto_table)
369
0
      / sizeof (elf_m68hc11_howto_table[0]));
370
0
       i++)
371
0
    if (elf_m68hc11_howto_table[i].name != NULL
372
0
  && strcasecmp (elf_m68hc11_howto_table[i].name, r_name) == 0)
373
0
      return &elf_m68hc11_howto_table[i];
374
375
0
  return NULL;
376
0
}
377
378
/* Set the howto pointer for an M68HC11 ELF reloc.  */
379
380
static bool
381
m68hc11_info_to_howto_rel (bfd *abfd,
382
         arelent *cache_ptr, Elf_Internal_Rela *dst)
383
0
{
384
0
  unsigned int r_type;
385
386
0
  r_type = ELF32_R_TYPE (dst->r_info);
387
0
  if (r_type >= (unsigned int) R_M68HC11_max)
388
0
    {
389
      /* xgettext:c-format */
390
0
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
391
0
        abfd, r_type);
392
0
      bfd_set_error (bfd_error_bad_value);
393
0
      return false;
394
0
    }
395
0
  cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
396
0
  return true;
397
0
}
398
399

400
/* Far trampoline generation.  */
401
402
/* Build a 68HC11 trampoline stub.  */
403
static bool
404
m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
405
0
{
406
0
  struct elf32_m68hc11_stub_hash_entry *stub_entry;
407
0
  struct bfd_link_info *info;
408
0
  struct m68hc11_elf_link_hash_table *htab;
409
0
  asection *stub_sec;
410
0
  bfd *stub_bfd;
411
0
  bfd_byte *loc;
412
0
  bfd_vma sym_value, phys_page, phys_addr;
413
414
  /* Massage our args to the form they really have.  */
415
0
  stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
416
0
  info = (struct bfd_link_info *) in_arg;
417
418
  /* Fail if the target section could not be assigned to an output
419
     section.  The user should fix his linker script.  */
420
0
  if (stub_entry->target_section->output_section == NULL
421
0
      && info->non_contiguous_regions)
422
0
    info->callbacks->fatal (_("%P: Could not assign `%pA' to an output section. "
423
0
            "Retry without --enable-non-contiguous-regions.\n"),
424
0
          stub_entry->target_section);
425
426
0
  htab = m68hc11_elf_hash_table (info);
427
0
  if (htab == NULL)
428
0
    return false;
429
430
0
  stub_sec = stub_entry->stub_sec;
431
432
  /* Make a note of the offset within the stubs for this entry.  */
433
0
  stub_entry->stub_offset = stub_sec->size;
434
0
  stub_sec->size += 10;
435
0
  loc = stub_sec->contents + stub_entry->stub_offset;
436
437
0
  stub_bfd = stub_sec->owner;
438
439
  /* Create the trampoline call stub:
440
441
     pshb
442
     ldab #%page(symbol)
443
     ldy #%addr(symbol)
444
     jmp __trampoline
445
446
  */
447
0
  sym_value = (stub_entry->target_value
448
0
         + stub_entry->target_section->output_offset
449
0
         + stub_entry->target_section->output_section->vma);
450
0
  phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
451
0
  phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
452
453
  /* pshb; ldab #%page(sym) */
454
0
  bfd_put_8 (stub_bfd, 0x37, loc);
455
0
  bfd_put_8 (stub_bfd, 0xC6, loc + 1);
456
0
  bfd_put_8 (stub_bfd, phys_page, loc + 2);
457
0
  loc += 3;
458
459
  /* ldy #%addr(sym)  */
460
0
  bfd_put_8 (stub_bfd, 0x18, loc);
461
0
  bfd_put_8 (stub_bfd, 0xCE, loc + 1);
462
0
  bfd_put_16 (stub_bfd, phys_addr, loc + 2);
463
0
  loc += 4;
464
465
  /* jmp __trampoline  */
466
0
  bfd_put_8 (stub_bfd, 0x7E, loc);
467
0
  bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
468
469
0
  return true;
470
0
}
471
472
/* As above, but don't actually build the stub.  Just bump offset so
473
   we know stub section sizes.  */
474
475
static bool
476
m68hc11_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
477
         void *in_arg ATTRIBUTE_UNUSED)
478
0
{
479
0
  struct elf32_m68hc11_stub_hash_entry *stub_entry;
480
481
  /* Massage our args to the form they really have.  */
482
0
  stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
483
484
0
  stub_entry->stub_sec->size += 10;
485
0
  return true;
486
0
}
487
488
/* Create a 68HC11 ELF linker hash table.  */
489
490
static struct bfd_link_hash_table *
491
m68hc11_elf_bfd_link_hash_table_create (bfd *abfd)
492
0
{
493
0
  struct m68hc11_elf_link_hash_table *ret;
494
495
0
  ret = m68hc11_elf_hash_table_create (abfd);
496
0
  if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
497
0
    return NULL;
498
499
0
  ret->size_one_stub = m68hc11_elf_size_one_stub;
500
0
  ret->build_one_stub = m68hc11_elf_build_one_stub;
501
502
0
  return &ret->root.root;
503
0
}
504
505

506
/* 68HC11 Linker Relaxation.  */
507
508
const struct m68hc11_direct_relax
509
{
510
  const char *name;
511
  unsigned char code;
512
  unsigned char direct_code;
513
} m68hc11_direct_relax_table[] = {
514
  { "adca", 0xB9, 0x99 },
515
  { "adcb", 0xF9, 0xD9 },
516
  { "adda", 0xBB, 0x9B },
517
  { "addb", 0xFB, 0xDB },
518
  { "addd", 0xF3, 0xD3 },
519
  { "anda", 0xB4, 0x94 },
520
  { "andb", 0xF4, 0xD4 },
521
  { "cmpa", 0xB1, 0x91 },
522
  { "cmpb", 0xF1, 0xD1 },
523
  { "cpd",  0xB3, 0x93 },
524
  { "cpxy", 0xBC, 0x9C },
525
/* { "cpy",  0xBC, 0x9C }, */
526
  { "eora", 0xB8, 0x98 },
527
  { "eorb", 0xF8, 0xD8 },
528
  { "jsr",  0xBD, 0x9D },
529
  { "ldaa", 0xB6, 0x96 },
530
  { "ldab", 0xF6, 0xD6 },
531
  { "ldd",  0xFC, 0xDC },
532
  { "lds",  0xBE, 0x9E },
533
  { "ldxy", 0xFE, 0xDE },
534
  /*  { "ldy",  0xFE, 0xDE },*/
535
  { "oraa", 0xBA, 0x9A },
536
  { "orab", 0xFA, 0xDA },
537
  { "sbca", 0xB2, 0x92 },
538
  { "sbcb", 0xF2, 0xD2 },
539
  { "staa", 0xB7, 0x97 },
540
  { "stab", 0xF7, 0xD7 },
541
  { "std",  0xFD, 0xDD },
542
  { "sts",  0xBF, 0x9F },
543
  { "stxy", 0xFF, 0xDF },
544
  /*  { "sty",  0xFF, 0xDF },*/
545
  { "suba", 0xB0, 0x90 },
546
  { "subb", 0xF0, 0xD0 },
547
  { "subd", 0xB3, 0x93 },
548
  { 0, 0, 0 }
549
};
550
551
static const struct m68hc11_direct_relax *
552
find_relaxable_insn (unsigned char code)
553
0
{
554
0
  int i;
555
556
0
  for (i = 0; m68hc11_direct_relax_table[i].name; i++)
557
0
    if (m68hc11_direct_relax_table[i].code == code)
558
0
      return &m68hc11_direct_relax_table[i];
559
560
0
  return 0;
561
0
}
562
563
static int
564
compare_reloc (const void *e1, const void *e2)
565
0
{
566
0
  const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
567
0
  const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;
568
569
0
  if (i1->r_offset == i2->r_offset)
570
0
    return 0;
571
0
  else
572
0
    return i1->r_offset < i2->r_offset ? -1 : 1;
573
0
}
574
575
0
#define M6811_OP_LDX_IMMEDIATE (0xCE)
576
577
static void
578
m68hc11_relax_group (bfd *abfd, asection *sec, bfd_byte *contents,
579
         unsigned value, unsigned long offset,
580
         unsigned long end_group)
581
0
{
582
0
  unsigned char code;
583
0
  unsigned long start_offset;
584
0
  unsigned long ldx_offset = offset;
585
0
  unsigned long ldx_size;
586
0
  int can_delete_ldx;
587
0
  int relax_ldy = 0;
588
589
  /* First instruction of the relax group must be a
590
     LDX #value or LDY #value.  If this is not the case,
591
     ignore the relax group.  */
592
0
  code = bfd_get_8 (abfd, contents + offset);
593
0
  if (code == 0x18)
594
0
    {
595
0
      relax_ldy++;
596
0
      offset++;
597
0
      code = bfd_get_8 (abfd, contents + offset);
598
0
    }
599
0
  ldx_size = offset - ldx_offset + 3;
600
0
  offset += 3;
601
0
  if (code != M6811_OP_LDX_IMMEDIATE || offset >= end_group)
602
0
    return;
603
604
605
  /* We can remove the LDX/LDY only when all bset/brclr instructions
606
     of the relax group have been converted to use direct addressing
607
     mode.  */
608
0
  can_delete_ldx = 1;
609
0
  while (offset < end_group)
610
0
    {
611
0
      unsigned isize;
612
0
      unsigned new_value;
613
0
      int bset_use_y;
614
615
0
      bset_use_y = 0;
616
0
      start_offset = offset;
617
0
      code = bfd_get_8 (abfd, contents + offset);
618
0
      if (code == 0x18)
619
0
  {
620
0
    bset_use_y++;
621
0
    offset++;
622
0
    code = bfd_get_8 (abfd, contents + offset);
623
0
  }
624
625
      /* Check the instruction and translate to use direct addressing mode.  */
626
0
      switch (code)
627
0
  {
628
    /* bset */
629
0
  case 0x1C:
630
0
    code = 0x14;
631
0
    isize = 3;
632
0
    break;
633
634
    /* brclr */
635
0
  case 0x1F:
636
0
    code = 0x13;
637
0
    isize = 4;
638
0
    break;
639
640
    /* brset */
641
0
  case 0x1E:
642
0
    code = 0x12;
643
0
    isize = 4;
644
0
    break;
645
646
    /* bclr */
647
0
  case 0x1D:
648
0
    code = 0x15;
649
0
    isize = 3;
650
0
    break;
651
652
    /* This instruction is not recognized and we are not
653
       at end of the relax group.  Ignore and don't remove
654
       the first LDX (we don't know what it is used for...).  */
655
0
  default:
656
0
    return;
657
0
  }
658
0
      new_value = (unsigned) bfd_get_8 (abfd, contents + offset + 1);
659
0
      new_value += value;
660
0
      if ((new_value & 0xff00) == 0 && bset_use_y == relax_ldy)
661
0
  {
662
0
    bfd_put_8 (abfd, code, contents + offset);
663
0
    bfd_put_8 (abfd, new_value, contents + offset + 1);
664
0
    if (start_offset != offset)
665
0
      {
666
0
        m68hc11_elf_relax_delete_bytes (abfd, sec, start_offset,
667
0
                offset - start_offset);
668
0
        end_group--;
669
0
      }
670
0
  }
671
0
      else
672
0
  {
673
0
    can_delete_ldx = 0;
674
0
  }
675
0
      offset = start_offset + isize;
676
0
    }
677
0
  if (can_delete_ldx)
678
0
    {
679
      /* Remove the move instruction (3 or 4 bytes win).  */
680
0
      m68hc11_elf_relax_delete_bytes (abfd, sec, ldx_offset, ldx_size);
681
0
    }
682
0
}
683
684
/* This function handles relaxing for the 68HC11.
685
686
687
  and somewhat more difficult to support.  */
688
689
static bool
690
m68hc11_elf_relax_section (bfd *abfd, asection *sec,
691
         struct bfd_link_info *link_info, bool *again)
692
0
{
693
0
  Elf_Internal_Shdr *symtab_hdr;
694
0
  Elf_Internal_Rela *internal_relocs;
695
0
  Elf_Internal_Rela *free_relocs = NULL;
696
0
  Elf_Internal_Rela *irel, *irelend;
697
0
  bfd_byte *contents = NULL;
698
0
  bfd_byte *free_contents = NULL;
699
0
  Elf32_External_Sym *free_extsyms = NULL;
700
0
  Elf_Internal_Rela *prev_insn_branch = NULL;
701
0
  Elf_Internal_Rela *prev_insn_group = NULL;
702
0
  unsigned insn_group_value = 0;
703
0
  Elf_Internal_Sym *isymbuf = NULL;
704
705
  /* Assume nothing changes.  */
706
0
  *again = false;
707
708
  /* We don't have to do anything for a relocatable link, if
709
     this section does not have relocs, or if this is not a
710
     code section.  */
711
0
  if (bfd_link_relocatable (link_info)
712
0
      || sec->reloc_count == 0
713
0
      || (sec->flags & SEC_RELOC) == 0
714
0
      || (sec->flags & SEC_HAS_CONTENTS) == 0
715
0
      || (sec->flags & SEC_CODE) == 0)
716
0
    return true;
717
718
0
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
719
720
  /* Get a copy of the native relocations.  */
721
0
  internal_relocs = (_bfd_elf_link_read_relocs
722
0
         (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
723
0
          link_info->keep_memory));
724
0
  if (internal_relocs == NULL)
725
0
    goto error_return;
726
0
  if (! link_info->keep_memory)
727
0
    free_relocs = internal_relocs;
728
729
  /* Checking for branch relaxation relies on the relocations to
730
     be sorted on 'r_offset'.  This is not guaranteed so we must sort.  */
731
0
  qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
732
0
   compare_reloc);
733
734
  /* Walk through them looking for relaxing opportunities.  */
735
0
  irelend = internal_relocs + sec->reloc_count;
736
0
  for (irel = internal_relocs; irel < irelend; irel++)
737
0
    {
738
0
      bfd_vma symval;
739
0
      bfd_vma value;
740
0
      Elf_Internal_Sym *isym;
741
0
      asection *sym_sec;
742
0
      int is_far = 0;
743
744
      /* If this isn't something that can be relaxed, then ignore
745
   this reloc.  */
746
0
      if (ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_16
747
0
    && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_JUMP
748
0
    && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_GROUP)
749
0
  {
750
0
    prev_insn_branch = 0;
751
0
    prev_insn_group = 0;
752
0
    continue;
753
0
  }
754
755
      /* Get the section contents if we haven't done so already.  */
756
0
      if (contents == NULL)
757
0
  {
758
    /* Get cached copy if it exists.  */
759
0
    if (elf_section_data (sec)->this_hdr.contents != NULL)
760
0
      contents = elf_section_data (sec)->this_hdr.contents;
761
0
    else
762
0
      {
763
        /* Go get them off disk.  */
764
0
        if (!bfd_malloc_and_get_section (abfd, sec, &contents))
765
0
    goto error_return;
766
0
      }
767
0
  }
768
769
      /* Try to eliminate an unconditional 8 bit pc-relative branch
770
   which immediately follows a conditional 8 bit pc-relative
771
   branch around the unconditional branch.
772
773
      original:   new:
774
      bCC lab1    bCC' lab2
775
      bra lab2
776
     lab1:         lab1:
777
778
   This happens when the bCC can't reach lab2 at assembly time,
779
   but due to other relaxations it can reach at link time.  */
780
0
      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_JUMP)
781
0
  {
782
0
    Elf_Internal_Rela *nrel;
783
0
    unsigned char code;
784
0
    unsigned char roffset;
785
786
0
    prev_insn_branch = 0;
787
0
    prev_insn_group = 0;
788
789
    /* Do nothing if this reloc is the last byte in the section.  */
790
0
    if (irel->r_offset + 2 >= sec->size)
791
0
      continue;
792
793
    /* See if the next instruction is an unconditional pc-relative
794
       branch, more often than not this test will fail, so we
795
       test it first to speed things up.  */
796
0
    code = bfd_get_8 (abfd, contents + irel->r_offset + 2);
797
0
    if (code != 0x7e)
798
0
      continue;
799
800
    /* Also make sure the next relocation applies to the next
801
       instruction and that it's a pc-relative 8 bit branch.  */
802
0
    nrel = irel + 1;
803
0
    if (nrel == irelend
804
0
        || irel->r_offset + 3 != nrel->r_offset
805
0
        || ELF32_R_TYPE (nrel->r_info) != (int) R_M68HC11_16)
806
0
      continue;
807
808
    /* Make sure our destination immediately follows the
809
       unconditional branch.  */
810
0
    roffset = bfd_get_8 (abfd, contents + irel->r_offset + 1);
811
0
    if (roffset != 3)
812
0
      continue;
813
814
0
    prev_insn_branch = irel;
815
0
    prev_insn_group = 0;
816
0
    continue;
817
0
  }
818
819
      /* Read this BFD's symbols if we haven't done so already.  */
820
0
      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
821
0
  {
822
0
    isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
823
0
    if (isymbuf == NULL)
824
0
      isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
825
0
              symtab_hdr->sh_info, 0,
826
0
              NULL, NULL, NULL);
827
0
    if (isymbuf == NULL)
828
0
      goto error_return;
829
0
  }
830
831
      /* Get the value of the symbol referred to by the reloc.  */
832
0
      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
833
0
  {
834
    /* A local symbol.  */
835
0
    isym = isymbuf + ELF32_R_SYM (irel->r_info);
836
0
    is_far = isym->st_other & STO_M68HC12_FAR;
837
0
    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
838
0
    symval = (isym->st_value
839
0
        + sym_sec->output_section->vma
840
0
        + sym_sec->output_offset);
841
0
  }
842
0
      else
843
0
  {
844
0
    unsigned long indx;
845
0
    struct elf_link_hash_entry *h;
846
847
    /* An external symbol.  */
848
0
    indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
849
0
    h = elf_sym_hashes (abfd)[indx];
850
0
    BFD_ASSERT (h != NULL);
851
0
    if (h->root.type != bfd_link_hash_defined
852
0
        && h->root.type != bfd_link_hash_defweak)
853
0
      {
854
        /* This appears to be a reference to an undefined
855
     symbol.  Just ignore it--it will be caught by the
856
     regular reloc processing.  */
857
0
        prev_insn_branch = 0;
858
0
        prev_insn_group = 0;
859
0
        continue;
860
0
      }
861
862
0
    is_far = h->other & STO_M68HC12_FAR;
863
0
    isym = 0;
864
0
    sym_sec = h->root.u.def.section;
865
0
    symval = (h->root.u.def.value
866
0
        + sym_sec->output_section->vma
867
0
        + sym_sec->output_offset);
868
0
  }
869
870
0
      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
871
0
  {
872
0
    prev_insn_branch = 0;
873
0
    prev_insn_group = 0;
874
875
    /* Do nothing if this reloc is the last byte in the section.  */
876
0
    if (irel->r_offset == sec->size)
877
0
      continue;
878
879
0
    prev_insn_group = irel;
880
0
    insn_group_value = isym->st_value;
881
0
    continue;
882
0
  }
883
884
      /* When we relax some bytes, the size of our section changes.
885
   This affects the layout of next input sections that go in our
886
   output section.  When the symbol is part of another section that
887
   will go in the same output section as the current one, it's
888
   final address may now be incorrect (too far).  We must let the
889
   linker re-compute all section offsets before processing this
890
   reloc.  Code example:
891
892
        Initial       Final
893
   .sect .text    section size = 6    section size = 4
894
   jmp foo
895
   jmp bar
896
   .sect .text.foo_bar  output_offset = 6   output_offset = 4
897
   foo: rts
898
   bar: rts
899
900
   If we process the reloc now, the jmp bar is replaced by a
901
   relative branch to the initial bar address (output_offset 6).  */
902
0
      if (*again && sym_sec != sec
903
0
    && sym_sec->output_section == sec->output_section)
904
0
  {
905
0
    prev_insn_group = 0;
906
0
    prev_insn_branch = 0;
907
0
    continue;
908
0
  }
909
910
0
      value = symval;
911
      /* Try to turn a far branch to a near branch.  */
912
0
      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
913
0
    && prev_insn_branch)
914
0
  {
915
0
    bfd_vma offset;
916
0
    unsigned char code;
917
918
0
    offset = value - (prev_insn_branch->r_offset
919
0
          + sec->output_section->vma
920
0
          + sec->output_offset + 2);
921
922
    /* If the offset is still out of -128..+127 range,
923
       leave that far branch unchanged.  */
924
0
    if ((offset & 0xff80) != 0 && (offset & 0xff80) != 0xff80)
925
0
      {
926
0
        prev_insn_branch = 0;
927
0
        continue;
928
0
      }
929
930
    /* Shrink the branch.  */
931
0
    code = bfd_get_8 (abfd, contents + prev_insn_branch->r_offset);
932
0
    if (code == 0x7e)
933
0
      {
934
0
        code = 0x20;
935
0
        bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
936
0
        bfd_put_8 (abfd, 0xff,
937
0
       contents + prev_insn_branch->r_offset + 1);
938
0
        irel->r_offset = prev_insn_branch->r_offset + 1;
939
0
        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
940
0
             R_M68HC11_PCREL_8);
941
0
        m68hc11_elf_relax_delete_bytes (abfd, sec,
942
0
                irel->r_offset + 1, 1);
943
0
      }
944
0
    else
945
0
      {
946
0
        code ^= 0x1;
947
0
        bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
948
0
        bfd_put_8 (abfd, 0xff,
949
0
       contents + prev_insn_branch->r_offset + 1);
950
0
        irel->r_offset = prev_insn_branch->r_offset + 1;
951
0
        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
952
0
             R_M68HC11_PCREL_8);
953
0
        m68hc11_elf_relax_delete_bytes (abfd, sec,
954
0
                irel->r_offset + 1, 3);
955
0
      }
956
0
    prev_insn_branch = 0;
957
0
    *again = true;
958
0
  }
959
960
      /* Try to turn a 16 bit address into a 8 bit page0 address.  */
961
0
      else if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
962
0
         && (value & 0xff00) == 0)
963
0
  {
964
0
    unsigned char code;
965
0
    unsigned short offset;
966
0
    const struct m68hc11_direct_relax *rinfo;
967
968
0
    prev_insn_branch = 0;
969
0
    offset = bfd_get_16 (abfd, contents + irel->r_offset);
970
0
    offset += value;
971
0
    if ((offset & 0xff00) != 0)
972
0
      {
973
0
        prev_insn_group = 0;
974
0
        continue;
975
0
      }
976
977
0
    if (prev_insn_group)
978
0
      {
979
0
        unsigned long old_sec_size = sec->size;
980
981
        /* Note that we've changed the relocation contents, etc.  */
982
0
        elf_section_data (sec)->relocs = internal_relocs;
983
0
        free_relocs = NULL;
984
985
0
        elf_section_data (sec)->this_hdr.contents = contents;
986
0
        free_contents = NULL;
987
988
0
        symtab_hdr->contents = (bfd_byte *) isymbuf;
989
0
        free_extsyms = NULL;
990
991
0
        m68hc11_relax_group (abfd, sec, contents, offset,
992
0
           prev_insn_group->r_offset,
993
0
           insn_group_value);
994
0
        irel = prev_insn_group;
995
0
        prev_insn_group = 0;
996
0
        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
997
0
             R_M68HC11_NONE);
998
0
        if (sec->size != old_sec_size)
999
0
    *again = true;
1000
0
        continue;
1001
0
      }
1002
1003
    /* Get the opcode.  */
1004
0
    code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
1005
0
    rinfo = find_relaxable_insn (code);
1006
0
    if (rinfo == 0)
1007
0
      {
1008
0
        prev_insn_group = 0;
1009
0
        continue;
1010
0
      }
1011
1012
    /* Note that we've changed the relocation contents, etc.  */
1013
0
    elf_section_data (sec)->relocs = internal_relocs;
1014
0
    free_relocs = NULL;
1015
1016
0
    elf_section_data (sec)->this_hdr.contents = contents;
1017
0
    free_contents = NULL;
1018
1019
0
    symtab_hdr->contents = (bfd_byte *) isymbuf;
1020
0
    free_extsyms = NULL;
1021
1022
    /* Fix the opcode.  */
1023
    /* printf ("A relaxable case : 0x%02x (%s)\n",
1024
       code, rinfo->name); */
1025
0
    bfd_put_8 (abfd, rinfo->direct_code,
1026
0
         contents + irel->r_offset - 1);
1027
1028
    /* Delete one byte of data (upper byte of address).  */
1029
0
    m68hc11_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 1);
1030
1031
    /* Fix the relocation's type.  */
1032
0
    irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1033
0
               R_M68HC11_8);
1034
1035
    /* That will change things, so, we should relax again.  */
1036
0
    *again = true;
1037
0
  }
1038
0
      else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16 && !is_far)
1039
0
  {
1040
0
    unsigned char code;
1041
0
    bfd_vma offset;
1042
1043
0
    prev_insn_branch = 0;
1044
0
    code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
1045
0
    if (code == 0x7e || code == 0xbd)
1046
0
      {
1047
0
        offset = value - (irel->r_offset
1048
0
        + sec->output_section->vma
1049
0
        + sec->output_offset + 1);
1050
0
        offset += bfd_get_16 (abfd, contents + irel->r_offset);
1051
1052
        /* If the offset is still out of -128..+127 range,
1053
     leave that far branch unchanged.  */
1054
0
        if ((offset & 0xff80) == 0 || (offset & 0xff80) == 0xff80)
1055
0
    {
1056
1057
      /* Note that we've changed the relocation contents, etc.  */
1058
0
      elf_section_data (sec)->relocs = internal_relocs;
1059
0
      free_relocs = NULL;
1060
1061
0
      elf_section_data (sec)->this_hdr.contents = contents;
1062
0
      free_contents = NULL;
1063
1064
0
      symtab_hdr->contents = (bfd_byte *) isymbuf;
1065
0
      free_extsyms = NULL;
1066
1067
      /* Shrink the branch.  */
1068
0
      code = (code == 0x7e) ? 0x20 : 0x8d;
1069
0
      bfd_put_8 (abfd, code,
1070
0
           contents + irel->r_offset - 1);
1071
0
      bfd_put_8 (abfd, 0xff,
1072
0
           contents + irel->r_offset);
1073
0
      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1074
0
                 R_M68HC11_PCREL_8);
1075
0
      m68hc11_elf_relax_delete_bytes (abfd, sec,
1076
0
              irel->r_offset + 1, 1);
1077
      /* That will change things, so, we should relax again.  */
1078
0
      *again = true;
1079
0
    }
1080
0
      }
1081
0
  }
1082
0
      prev_insn_branch = 0;
1083
0
      prev_insn_group = 0;
1084
0
    }
1085
1086
0
  free (free_relocs);
1087
0
  free_relocs = NULL;
1088
1089
0
  if (free_contents != NULL)
1090
0
    {
1091
0
      if (! link_info->keep_memory)
1092
0
  free (free_contents);
1093
0
      else
1094
0
  {
1095
    /* Cache the section contents for elf_link_input_bfd.  */
1096
0
    elf_section_data (sec)->this_hdr.contents = contents;
1097
0
  }
1098
0
      free_contents = NULL;
1099
0
    }
1100
1101
0
  if (free_extsyms != NULL)
1102
0
    {
1103
0
      if (! link_info->keep_memory)
1104
0
  free (free_extsyms);
1105
0
      else
1106
0
  {
1107
    /* Cache the symbols for elf_link_input_bfd.  */
1108
0
    symtab_hdr->contents = (unsigned char *) isymbuf;
1109
0
  }
1110
0
      free_extsyms = NULL;
1111
0
    }
1112
1113
0
  return true;
1114
1115
0
 error_return:
1116
0
  free (free_relocs);
1117
0
  free (free_contents);
1118
0
  free (free_extsyms);
1119
0
  return false;
1120
0
}
1121
1122
/* Delete some bytes from a section while relaxing.  */
1123
1124
static void
1125
m68hc11_elf_relax_delete_bytes (bfd *abfd, asection *sec,
1126
        bfd_vma addr, int count)
1127
0
{
1128
0
  Elf_Internal_Shdr *symtab_hdr;
1129
0
  unsigned int sec_shndx;
1130
0
  bfd_byte *contents;
1131
0
  Elf_Internal_Rela *irel, *irelend;
1132
0
  bfd_vma toaddr;
1133
0
  Elf_Internal_Sym *isymbuf, *isym, *isymend;
1134
0
  struct elf_link_hash_entry **sym_hashes;
1135
0
  struct elf_link_hash_entry **end_hashes;
1136
0
  unsigned int symcount;
1137
1138
0
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1139
0
  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1140
1141
0
  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1142
1143
0
  contents = elf_section_data (sec)->this_hdr.contents;
1144
1145
0
  toaddr = sec->size;
1146
1147
0
  irel = elf_section_data (sec)->relocs;
1148
0
  irelend = irel + sec->reloc_count;
1149
1150
  /* Actually delete the bytes.  */
1151
0
  memmove (contents + addr, contents + addr + count,
1152
0
     (size_t) (toaddr - addr - count));
1153
1154
0
  sec->size -= count;
1155
1156
  /* Adjust all the relocs.  */
1157
0
  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1158
0
    {
1159
0
      unsigned char code;
1160
0
      unsigned char offset;
1161
0
      unsigned short raddr;
1162
0
      unsigned long old_offset;
1163
0
      int branch_pos;
1164
1165
0
      old_offset = irel->r_offset;
1166
1167
      /* See if this reloc was for the bytes we have deleted, in which
1168
   case we no longer care about it.  Don't delete relocs which
1169
   represent addresses, though.  */
1170
0
      if (ELF32_R_TYPE (irel->r_info) != R_M68HC11_RL_JUMP
1171
0
    && irel->r_offset >= addr && irel->r_offset < addr + count)
1172
0
  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1173
0
             R_M68HC11_NONE);
1174
1175
0
      if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_NONE)
1176
0
  continue;
1177
1178
      /* Get the new reloc address.  */
1179
0
      if ((irel->r_offset > addr
1180
0
     && irel->r_offset < toaddr))
1181
0
  irel->r_offset -= count;
1182
1183
      /* If this is a PC relative reloc, see if the range it covers
1184
   includes the bytes we have deleted.  */
1185
0
      switch (ELF32_R_TYPE (irel->r_info))
1186
0
  {
1187
0
  default:
1188
0
    break;
1189
1190
0
  case R_M68HC11_RL_JUMP:
1191
0
    code = bfd_get_8 (abfd, contents + irel->r_offset);
1192
0
    switch (code)
1193
0
      {
1194
        /* jsr and jmp instruction are also marked with RL_JUMP
1195
     relocs but no adjustment must be made.  */
1196
0
      case 0x7e:
1197
0
      case 0x9d:
1198
0
      case 0xbd:
1199
0
        continue;
1200
1201
0
      case 0x12:
1202
0
      case 0x13:
1203
0
        branch_pos = 3;
1204
0
        raddr = 4;
1205
1206
        /* Special case when we translate a brclr N,y into brclr *<addr>
1207
     In this case, the 0x18 page2 prefix is removed.
1208
     The reloc offset is not modified but the instruction
1209
     size is reduced by 1.  */
1210
0
        if (old_offset == addr)
1211
0
    raddr++;
1212
0
        break;
1213
1214
0
      case 0x1e:
1215
0
      case 0x1f:
1216
0
        branch_pos = 3;
1217
0
        raddr = 4;
1218
0
        break;
1219
1220
0
      case 0x18:
1221
0
        branch_pos = 4;
1222
0
        raddr = 5;
1223
0
        break;
1224
1225
0
      default:
1226
0
        branch_pos = 1;
1227
0
        raddr = 2;
1228
0
        break;
1229
0
      }
1230
0
    offset = bfd_get_8 (abfd, contents + irel->r_offset + branch_pos);
1231
0
    raddr += old_offset;
1232
0
    raddr += ((unsigned short) offset | ((offset & 0x80) ? 0xff00 : 0));
1233
0
    if (irel->r_offset < addr && raddr > addr)
1234
0
      {
1235
0
        offset -= count;
1236
0
        bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
1237
0
      }
1238
0
    else if (irel->r_offset >= addr && raddr <= addr)
1239
0
      {
1240
0
        offset += count;
1241
0
        bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
1242
0
      }
1243
0
    else
1244
0
      {
1245
        /*printf ("Not adjusted 0x%04x [0x%4x 0x%4x]\n", raddr,
1246
    irel->r_offset, addr);*/
1247
0
      }
1248
1249
0
    break;
1250
0
  }
1251
0
    }
1252
1253
  /* Adjust the local symbols defined in this section.  */
1254
0
  isymend = isymbuf + symtab_hdr->sh_info;
1255
0
  for (isym = isymbuf; isym < isymend; isym++)
1256
0
    {
1257
0
      if (isym->st_shndx == sec_shndx
1258
0
    && isym->st_value > addr
1259
0
    && isym->st_value <= toaddr)
1260
0
  isym->st_value -= count;
1261
0
    }
1262
1263
  /* Now adjust the global symbols defined in this section.  */
1264
0
  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1265
0
        - symtab_hdr->sh_info);
1266
0
  sym_hashes = elf_sym_hashes (abfd);
1267
0
  end_hashes = sym_hashes + symcount;
1268
0
  for (; sym_hashes < end_hashes; sym_hashes++)
1269
0
    {
1270
0
      struct elf_link_hash_entry *sym_hash = *sym_hashes;
1271
0
      if ((sym_hash->root.type == bfd_link_hash_defined
1272
0
     || sym_hash->root.type == bfd_link_hash_defweak)
1273
0
    && sym_hash->root.u.def.section == sec
1274
0
    && sym_hash->root.u.def.value > addr
1275
0
    && sym_hash->root.u.def.value <= toaddr)
1276
0
  {
1277
0
    sym_hash->root.u.def.value -= count;
1278
0
  }
1279
0
    }
1280
0
}
1281
1282
/* Specific sections:
1283
   - The .page0 is a data section that is mapped in [0x0000..0x00FF].
1284
     Page0 accesses are faster on the M68HC11. Soft registers used by GCC-m6811
1285
     are located in .page0.
1286
   - The .vectors is the section that represents the interrupt
1287
     vectors.  */
1288
static const struct bfd_elf_special_section elf32_m68hc11_special_sections[] =
1289
{
1290
  { STRING_COMMA_LEN (".eeprom"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
1291
  { STRING_COMMA_LEN (".page0"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
1292
  { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
1293
  { STRING_COMMA_LEN (".vectors"),  0, SHT_PROGBITS, SHF_ALLOC },
1294
  { NULL,     0,  0, 0,      0 }
1295
};
1296

1297
#define ELF_ARCH    bfd_arch_m68hc11
1298
#define ELF_TARGET_ID   M68HC11_ELF_DATA
1299
#define ELF_MACHINE_CODE  EM_68HC11
1300
#define ELF_MAXPAGESIZE   0x1000
1301
1302
#define TARGET_BIG_SYM    m68hc11_elf32_vec
1303
#define TARGET_BIG_NAME   "elf32-m68hc11"
1304
1305
#define elf_info_to_howto NULL
1306
#define elf_info_to_howto_rel m68hc11_info_to_howto_rel
1307
#define bfd_elf32_bfd_relax_section  m68hc11_elf_relax_section
1308
#define elf_backend_check_relocs     elf32_m68hc11_check_relocs
1309
#define elf_backend_relocate_section elf32_m68hc11_relocate_section
1310
#define elf_backend_add_symbol_hook  elf32_m68hc11_add_symbol_hook
1311
#define elf_backend_object_p  0
1312
#define elf_backend_can_gc_sections   1
1313
#define elf_backend_special_sections  elf32_m68hc11_special_sections
1314
#define elf_backend_merge_symbol_attribute elf32_m68hc11_merge_symbol_attribute
1315
1316
#define bfd_elf32_bfd_link_hash_table_create \
1317
        m68hc11_elf_bfd_link_hash_table_create
1318
#define bfd_elf32_bfd_merge_private_bfd_data \
1319
          _bfd_m68hc11_elf_merge_private_bfd_data
1320
#define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
1321
#define bfd_elf32_bfd_print_private_bfd_data \
1322
          _bfd_m68hc11_elf_print_private_bfd_data
1323
1324
#include "elf32-target.h"