1 /* Motorola 68HC11-specific support for 32-bit ELF
2    Copyright (C) 1999-2024 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 *
bfd_elf32_bfd_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)345 bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
346                                          bfd_reloc_code_real_type code)
347 {
348   unsigned int i;
349 
350   for (i = 0;
351        i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
352        i++)
353     {
354       if (m68hc11_reloc_map[i].bfd_reloc_val == code)
355           return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
356     }
357 
358   return NULL;
359 }
360 
361 static reloc_howto_type *
bfd_elf32_bfd_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)362 bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
363                                          const char *r_name)
364 {
365   unsigned int i;
366 
367   for (i = 0;
368        i < (sizeof (elf_m68hc11_howto_table)
369               / sizeof (elf_m68hc11_howto_table[0]));
370        i++)
371     if (elf_m68hc11_howto_table[i].name != NULL
372           && strcasecmp (elf_m68hc11_howto_table[i].name, r_name) == 0)
373       return &elf_m68hc11_howto_table[i];
374 
375   return NULL;
376 }
377 
378 /* Set the howto pointer for an M68HC11 ELF reloc.  */
379 
380 static bool
m68hc11_info_to_howto_rel(bfd * abfd,arelent * cache_ptr,Elf_Internal_Rela * dst)381 m68hc11_info_to_howto_rel (bfd *abfd,
382                                  arelent *cache_ptr, Elf_Internal_Rela *dst)
383 {
384   unsigned int r_type;
385 
386   r_type = ELF32_R_TYPE (dst->r_info);
387   if (r_type >= (unsigned int) R_M68HC11_max)
388     {
389       /* xgettext:c-format */
390       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
391                                 abfd, r_type);
392       bfd_set_error (bfd_error_bad_value);
393       return false;
394     }
395   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
396   return true;
397 }
398 
399 
400 /* Far trampoline generation.  */
401 
402 /* Build a 68HC11 trampoline stub.  */
403 static bool
m68hc11_elf_build_one_stub(struct bfd_hash_entry * gen_entry,void * in_arg)404 m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
405 {
406   struct elf32_m68hc11_stub_hash_entry *stub_entry;
407   struct bfd_link_info *info;
408   struct m68hc11_elf_link_hash_table *htab;
409   asection *stub_sec;
410   bfd *stub_bfd;
411   bfd_byte *loc;
412   bfd_vma sym_value, phys_page, phys_addr;
413 
414   /* Massage our args to the form they really have.  */
415   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
416   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   if (stub_entry->target_section->output_section == NULL
421       && info->non_contiguous_regions)
422     info->callbacks->einfo (_("%F%P: Could not assign `%pA' to an output section. "
423                                     "Retry without --enable-non-contiguous-regions.\n"),
424                                   stub_entry->target_section);
425 
426   htab = m68hc11_elf_hash_table (info);
427   if (htab == NULL)
428     return false;
429 
430   stub_sec = stub_entry->stub_sec;
431 
432   /* Make a note of the offset within the stubs for this entry.  */
433   stub_entry->stub_offset = stub_sec->size;
434   stub_sec->size += 10;
435   loc = stub_sec->contents + stub_entry->stub_offset;
436 
437   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   sym_value = (stub_entry->target_value
448                  + stub_entry->target_section->output_offset
449                  + stub_entry->target_section->output_section->vma);
450   phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
451   phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
452 
453   /* pshb; ldab #%page(sym) */
454   bfd_put_8 (stub_bfd, 0x37, loc);
455   bfd_put_8 (stub_bfd, 0xC6, loc + 1);
456   bfd_put_8 (stub_bfd, phys_page, loc + 2);
457   loc += 3;
458 
459   /* ldy #%addr(sym)  */
460   bfd_put_8 (stub_bfd, 0x18, loc);
461   bfd_put_8 (stub_bfd, 0xCE, loc + 1);
462   bfd_put_16 (stub_bfd, phys_addr, loc + 2);
463   loc += 4;
464 
465   /* jmp __trampoline  */
466   bfd_put_8 (stub_bfd, 0x7E, loc);
467   bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
468 
469   return true;
470 }
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
m68hc11_elf_size_one_stub(struct bfd_hash_entry * gen_entry,void * in_arg ATTRIBUTE_UNUSED)476 m68hc11_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
477                                  void *in_arg ATTRIBUTE_UNUSED)
478 {
479   struct elf32_m68hc11_stub_hash_entry *stub_entry;
480 
481   /* Massage our args to the form they really have.  */
482   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
483 
484   stub_entry->stub_sec->size += 10;
485   return true;
486 }
487 
488 /* Create a 68HC11 ELF linker hash table.  */
489 
490 static struct bfd_link_hash_table *
m68hc11_elf_bfd_link_hash_table_create(bfd * abfd)491 m68hc11_elf_bfd_link_hash_table_create (bfd *abfd)
492 {
493   struct m68hc11_elf_link_hash_table *ret;
494 
495   ret = m68hc11_elf_hash_table_create (abfd);
496   if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
497     return NULL;
498 
499   ret->size_one_stub = m68hc11_elf_size_one_stub;
500   ret->build_one_stub = m68hc11_elf_build_one_stub;
501 
502   return &ret->root.root;
503 }
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 *
find_relaxable_insn(unsigned char code)552 find_relaxable_insn (unsigned char code)
553 {
554   int i;
555 
556   for (i = 0; m68hc11_direct_relax_table[i].name; i++)
557     if (m68hc11_direct_relax_table[i].code == code)
558       return &m68hc11_direct_relax_table[i];
559 
560   return 0;
561 }
562 
563 static int
compare_reloc(const void * e1,const void * e2)564 compare_reloc (const void *e1, const void *e2)
565 {
566   const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
567   const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;
568 
569   if (i1->r_offset == i2->r_offset)
570     return 0;
571   else
572     return i1->r_offset < i2->r_offset ? -1 : 1;
573 }
574 
575 #define M6811_OP_LDX_IMMEDIATE (0xCE)
576 
577 static void
m68hc11_relax_group(bfd * abfd,asection * sec,bfd_byte * contents,unsigned value,unsigned long offset,unsigned long end_group)578 m68hc11_relax_group (bfd *abfd, asection *sec, bfd_byte *contents,
579                          unsigned value, unsigned long offset,
580                          unsigned long end_group)
581 {
582   unsigned char code;
583   unsigned long start_offset;
584   unsigned long ldx_offset = offset;
585   unsigned long ldx_size;
586   int can_delete_ldx;
587   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   code = bfd_get_8 (abfd, contents + offset);
593   if (code == 0x18)
594     {
595       relax_ldy++;
596       offset++;
597       code = bfd_get_8 (abfd, contents + offset);
598     }
599   ldx_size = offset - ldx_offset + 3;
600   offset += 3;
601   if (code != M6811_OP_LDX_IMMEDIATE || offset >= end_group)
602     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   can_delete_ldx = 1;
609   while (offset < end_group)
610     {
611       unsigned isize;
612       unsigned new_value;
613       int bset_use_y;
614 
615       bset_use_y = 0;
616       start_offset = offset;
617       code = bfd_get_8 (abfd, contents + offset);
618       if (code == 0x18)
619           {
620             bset_use_y++;
621             offset++;
622             code = bfd_get_8 (abfd, contents + offset);
623           }
624 
625       /* Check the instruction and translate to use direct addressing mode.  */
626       switch (code)
627           {
628             /* bset */
629           case 0x1C:
630             code = 0x14;
631             isize = 3;
632             break;
633 
634             /* brclr */
635           case 0x1F:
636             code = 0x13;
637             isize = 4;
638             break;
639 
640             /* brset */
641           case 0x1E:
642             code = 0x12;
643             isize = 4;
644             break;
645 
646             /* bclr */
647           case 0x1D:
648             code = 0x15;
649             isize = 3;
650             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           default:
656             return;
657           }
658       new_value = (unsigned) bfd_get_8 (abfd, contents + offset + 1);
659       new_value += value;
660       if ((new_value & 0xff00) == 0 && bset_use_y == relax_ldy)
661           {
662             bfd_put_8 (abfd, code, contents + offset);
663             bfd_put_8 (abfd, new_value, contents + offset + 1);
664             if (start_offset != offset)
665               {
666                 m68hc11_elf_relax_delete_bytes (abfd, sec, start_offset,
667                                                         offset - start_offset);
668                 end_group--;
669               }
670           }
671       else
672           {
673             can_delete_ldx = 0;
674           }
675       offset = start_offset + isize;
676     }
677   if (can_delete_ldx)
678     {
679       /* Remove the move instruction (3 or 4 bytes win).  */
680       m68hc11_elf_relax_delete_bytes (abfd, sec, ldx_offset, ldx_size);
681     }
682 }
683 
684 /* This function handles relaxing for the 68HC11.
685 
686 
687           and somewhat more difficult to support.  */
688 
689 static bool
m68hc11_elf_relax_section(bfd * abfd,asection * sec,struct bfd_link_info * link_info,bool * again)690 m68hc11_elf_relax_section (bfd *abfd, asection *sec,
691                                  struct bfd_link_info *link_info, bool *again)
692 {
693   Elf_Internal_Shdr *symtab_hdr;
694   Elf_Internal_Rela *internal_relocs;
695   Elf_Internal_Rela *free_relocs = NULL;
696   Elf_Internal_Rela *irel, *irelend;
697   bfd_byte *contents = NULL;
698   bfd_byte *free_contents = NULL;
699   Elf32_External_Sym *free_extsyms = NULL;
700   Elf_Internal_Rela *prev_insn_branch = NULL;
701   Elf_Internal_Rela *prev_insn_group = NULL;
702   unsigned insn_group_value = 0;
703   Elf_Internal_Sym *isymbuf = NULL;
704 
705   /* Assume nothing changes.  */
706   *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   if (bfd_link_relocatable (link_info)
712       || sec->reloc_count == 0
713       || (sec->flags & SEC_RELOC) == 0
714       || (sec->flags & SEC_HAS_CONTENTS) == 0
715       || (sec->flags & SEC_CODE) == 0)
716     return true;
717 
718   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
719 
720   /* Get a copy of the native relocations.  */
721   internal_relocs = (_bfd_elf_link_read_relocs
722                          (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
723                           link_info->keep_memory));
724   if (internal_relocs == NULL)
725     goto error_return;
726   if (! link_info->keep_memory)
727     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   qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
732            compare_reloc);
733 
734   /* Walk through them looking for relaxing opportunities.  */
735   irelend = internal_relocs + sec->reloc_count;
736   for (irel = internal_relocs; irel < irelend; irel++)
737     {
738       bfd_vma symval;
739       bfd_vma value;
740       Elf_Internal_Sym *isym;
741       asection *sym_sec;
742       int is_far = 0;
743 
744       /* If this isn't something that can be relaxed, then ignore
745            this reloc.  */
746       if (ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_16
747             && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_JUMP
748             && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_GROUP)
749           {
750             prev_insn_branch = 0;
751             prev_insn_group = 0;
752             continue;
753           }
754 
755       /* Get the section contents if we haven't done so already.  */
756       if (contents == NULL)
757           {
758             /* Get cached copy if it exists.  */
759             if (elf_section_data (sec)->this_hdr.contents != NULL)
760               contents = elf_section_data (sec)->this_hdr.contents;
761             else
762               {
763                 /* Go get them off disk.  */
764                 if (!bfd_malloc_and_get_section (abfd, sec, &contents))
765                     goto error_return;
766               }
767           }
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       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_JUMP)
781           {
782             Elf_Internal_Rela *nrel;
783             unsigned char code;
784             unsigned char roffset;
785 
786             prev_insn_branch = 0;
787             prev_insn_group = 0;
788 
789             /* Do nothing if this reloc is the last byte in the section.  */
790             if (irel->r_offset + 2 >= sec->size)
791               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             code = bfd_get_8 (abfd, contents + irel->r_offset + 2);
797             if (code != 0x7e)
798               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             nrel = irel + 1;
803             if (nrel == irelend
804                 || irel->r_offset + 3 != nrel->r_offset
805                 || ELF32_R_TYPE (nrel->r_info) != (int) R_M68HC11_16)
806               continue;
807 
808             /* Make sure our destination immediately follows the
809                unconditional branch.  */
810             roffset = bfd_get_8 (abfd, contents + irel->r_offset + 1);
811             if (roffset != 3)
812               continue;
813 
814             prev_insn_branch = irel;
815             prev_insn_group = 0;
816             continue;
817           }
818 
819       /* Read this BFD's symbols if we haven't done so already.  */
820       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
821           {
822             isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
823             if (isymbuf == NULL)
824               isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
825                                                       symtab_hdr->sh_info, 0,
826                                                       NULL, NULL, NULL);
827             if (isymbuf == NULL)
828               goto error_return;
829           }
830 
831       /* Get the value of the symbol referred to by the reloc.  */
832       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
833           {
834             /* A local symbol.  */
835             isym = isymbuf + ELF32_R_SYM (irel->r_info);
836             is_far = isym->st_other & STO_M68HC12_FAR;
837             sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
838             symval = (isym->st_value
839                         + sym_sec->output_section->vma
840                         + sym_sec->output_offset);
841           }
842       else
843           {
844             unsigned long indx;
845             struct elf_link_hash_entry *h;
846 
847             /* An external symbol.  */
848             indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
849             h = elf_sym_hashes (abfd)[indx];
850             BFD_ASSERT (h != NULL);
851             if (h->root.type != bfd_link_hash_defined
852                 && h->root.type != bfd_link_hash_defweak)
853               {
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                 prev_insn_branch = 0;
858                 prev_insn_group = 0;
859                 continue;
860               }
861 
862             is_far = h->other & STO_M68HC12_FAR;
863             isym = 0;
864             sym_sec = h->root.u.def.section;
865             symval = (h->root.u.def.value
866                         + sym_sec->output_section->vma
867                         + sym_sec->output_offset);
868           }
869 
870       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
871           {
872             prev_insn_branch = 0;
873             prev_insn_group = 0;
874 
875             /* Do nothing if this reloc is the last byte in the section.  */
876             if (irel->r_offset == sec->size)
877               continue;
878 
879             prev_insn_group = irel;
880             insn_group_value = isym->st_value;
881             continue;
882           }
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       if (*again && sym_sec != sec
903             && sym_sec->output_section == sec->output_section)
904           {
905             prev_insn_group = 0;
906             prev_insn_branch = 0;
907             continue;
908           }
909 
910       value = symval;
911       /* Try to turn a far branch to a near branch.  */
912       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
913             && prev_insn_branch)
914           {
915             bfd_vma offset;
916             unsigned char code;
917 
918             offset = value - (prev_insn_branch->r_offset
919                                   + sec->output_section->vma
920                                   + sec->output_offset + 2);
921 
922             /* If the offset is still out of -128..+127 range,
923                leave that far branch unchanged.  */
924             if ((offset & 0xff80) != 0 && (offset & 0xff80) != 0xff80)
925               {
926                 prev_insn_branch = 0;
927                 continue;
928               }
929 
930             /* Shrink the branch.  */
931             code = bfd_get_8 (abfd, contents + prev_insn_branch->r_offset);
932             if (code == 0x7e)
933               {
934                 code = 0x20;
935                 bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
936                 bfd_put_8 (abfd, 0xff,
937                                contents + prev_insn_branch->r_offset + 1);
938                 irel->r_offset = prev_insn_branch->r_offset + 1;
939                 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
940                                                      R_M68HC11_PCREL_8);
941                 m68hc11_elf_relax_delete_bytes (abfd, sec,
942                                                         irel->r_offset + 1, 1);
943               }
944             else
945               {
946                 code ^= 0x1;
947                 bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
948                 bfd_put_8 (abfd, 0xff,
949                                contents + prev_insn_branch->r_offset + 1);
950                 irel->r_offset = prev_insn_branch->r_offset + 1;
951                 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
952                                                      R_M68HC11_PCREL_8);
953                 m68hc11_elf_relax_delete_bytes (abfd, sec,
954                                                         irel->r_offset + 1, 3);
955               }
956             prev_insn_branch = 0;
957             *again = true;
958           }
959 
960       /* Try to turn a 16 bit address into a 8 bit page0 address.  */
961       else if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
962                  && (value & 0xff00) == 0)
963           {
964             unsigned char code;
965             unsigned short offset;
966             const struct m68hc11_direct_relax *rinfo;
967 
968             prev_insn_branch = 0;
969             offset = bfd_get_16 (abfd, contents + irel->r_offset);
970             offset += value;
971             if ((offset & 0xff00) != 0)
972               {
973                 prev_insn_group = 0;
974                 continue;
975               }
976 
977             if (prev_insn_group)
978               {
979                 unsigned long old_sec_size = sec->size;
980 
981                 /* Note that we've changed the relocation contents, etc.  */
982                 elf_section_data (sec)->relocs = internal_relocs;
983                 free_relocs = NULL;
984 
985                 elf_section_data (sec)->this_hdr.contents = contents;
986                 free_contents = NULL;
987 
988                 symtab_hdr->contents = (bfd_byte *) isymbuf;
989                 free_extsyms = NULL;
990 
991                 m68hc11_relax_group (abfd, sec, contents, offset,
992                                            prev_insn_group->r_offset,
993                                            insn_group_value);
994                 irel = prev_insn_group;
995                 prev_insn_group = 0;
996                 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
997                                                      R_M68HC11_NONE);
998                 if (sec->size != old_sec_size)
999                     *again = true;
1000                 continue;
1001               }
1002 
1003             /* Get the opcode.  */
1004             code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
1005             rinfo = find_relaxable_insn (code);
1006             if (rinfo == 0)
1007               {
1008                 prev_insn_group = 0;
1009                 continue;
1010               }
1011 
1012             /* Note that we've changed the relocation contents, etc.  */
1013             elf_section_data (sec)->relocs = internal_relocs;
1014             free_relocs = NULL;
1015 
1016             elf_section_data (sec)->this_hdr.contents = contents;
1017             free_contents = NULL;
1018 
1019             symtab_hdr->contents = (bfd_byte *) isymbuf;
1020             free_extsyms = NULL;
1021 
1022             /* Fix the opcode.  */
1023             /* printf ("A relaxable case : 0x%02x (%s)\n",
1024                code, rinfo->name); */
1025             bfd_put_8 (abfd, rinfo->direct_code,
1026                          contents + irel->r_offset - 1);
1027 
1028             /* Delete one byte of data (upper byte of address).  */
1029             m68hc11_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 1);
1030 
1031             /* Fix the relocation's type.  */
1032             irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1033                                                R_M68HC11_8);
1034 
1035             /* That will change things, so, we should relax again.  */
1036             *again = true;
1037           }
1038       else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16 && !is_far)
1039           {
1040             unsigned char code;
1041             bfd_vma offset;
1042 
1043             prev_insn_branch = 0;
1044             code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
1045             if (code == 0x7e || code == 0xbd)
1046               {
1047                 offset = value - (irel->r_offset
1048                                         + sec->output_section->vma
1049                                         + sec->output_offset + 1);
1050                 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                 if ((offset & 0xff80) == 0 || (offset & 0xff80) == 0xff80)
1055                     {
1056 
1057                       /* Note that we've changed the relocation contents, etc.  */
1058                       elf_section_data (sec)->relocs = internal_relocs;
1059                       free_relocs = NULL;
1060 
1061                       elf_section_data (sec)->this_hdr.contents = contents;
1062                       free_contents = NULL;
1063 
1064                       symtab_hdr->contents = (bfd_byte *) isymbuf;
1065                       free_extsyms = NULL;
1066 
1067                       /* Shrink the branch.  */
1068                       code = (code == 0x7e) ? 0x20 : 0x8d;
1069                       bfd_put_8 (abfd, code,
1070                                    contents + irel->r_offset - 1);
1071                       bfd_put_8 (abfd, 0xff,
1072                                    contents + irel->r_offset);
1073                       irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1074                                                          R_M68HC11_PCREL_8);
1075                       m68hc11_elf_relax_delete_bytes (abfd, sec,
1076                                                               irel->r_offset + 1, 1);
1077                       /* That will change things, so, we should relax again.  */
1078                       *again = true;
1079                     }
1080               }
1081           }
1082       prev_insn_branch = 0;
1083       prev_insn_group = 0;
1084     }
1085 
1086   free (free_relocs);
1087   free_relocs = NULL;
1088 
1089   if (free_contents != NULL)
1090     {
1091       if (! link_info->keep_memory)
1092           free (free_contents);
1093       else
1094           {
1095             /* Cache the section contents for elf_link_input_bfd.  */
1096             elf_section_data (sec)->this_hdr.contents = contents;
1097           }
1098       free_contents = NULL;
1099     }
1100 
1101   if (free_extsyms != NULL)
1102     {
1103       if (! link_info->keep_memory)
1104           free (free_extsyms);
1105       else
1106           {
1107             /* Cache the symbols for elf_link_input_bfd.  */
1108             symtab_hdr->contents = (unsigned char *) isymbuf;
1109           }
1110       free_extsyms = NULL;
1111     }
1112 
1113   return true;
1114 
1115  error_return:
1116   free (free_relocs);
1117   free (free_contents);
1118   free (free_extsyms);
1119   return false;
1120 }
1121 
1122 /* Delete some bytes from a section while relaxing.  */
1123 
1124 static void
m68hc11_elf_relax_delete_bytes(bfd * abfd,asection * sec,bfd_vma addr,int count)1125 m68hc11_elf_relax_delete_bytes (bfd *abfd, asection *sec,
1126                                         bfd_vma addr, int count)
1127 {
1128   Elf_Internal_Shdr *symtab_hdr;
1129   unsigned int sec_shndx;
1130   bfd_byte *contents;
1131   Elf_Internal_Rela *irel, *irelend;
1132   bfd_vma toaddr;
1133   Elf_Internal_Sym *isymbuf, *isym, *isymend;
1134   struct elf_link_hash_entry **sym_hashes;
1135   struct elf_link_hash_entry **end_hashes;
1136   unsigned int symcount;
1137 
1138   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1139   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1140 
1141   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1142 
1143   contents = elf_section_data (sec)->this_hdr.contents;
1144 
1145   toaddr = sec->size;
1146 
1147   irel = elf_section_data (sec)->relocs;
1148   irelend = irel + sec->reloc_count;
1149 
1150   /* Actually delete the bytes.  */
1151   memmove (contents + addr, contents + addr + count,
1152              (size_t) (toaddr - addr - count));
1153 
1154   sec->size -= count;
1155 
1156   /* Adjust all the relocs.  */
1157   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1158     {
1159       unsigned char code;
1160       unsigned char offset;
1161       unsigned short raddr;
1162       unsigned long old_offset;
1163       int branch_pos;
1164 
1165       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       if (ELF32_R_TYPE (irel->r_info) != R_M68HC11_RL_JUMP
1171             && irel->r_offset >= addr && irel->r_offset < addr + count)
1172           irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1173                                              R_M68HC11_NONE);
1174 
1175       if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_NONE)
1176           continue;
1177 
1178       /* Get the new reloc address.  */
1179       if ((irel->r_offset > addr
1180              && irel->r_offset < toaddr))
1181           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       switch (ELF32_R_TYPE (irel->r_info))
1186           {
1187           default:
1188             break;
1189 
1190           case R_M68HC11_RL_JUMP:
1191             code = bfd_get_8 (abfd, contents + irel->r_offset);
1192             switch (code)
1193               {
1194                 /* jsr and jmp instruction are also marked with RL_JUMP
1195                      relocs but no adjustment must be made.  */
1196               case 0x7e:
1197               case 0x9d:
1198               case 0xbd:
1199                 continue;
1200 
1201               case 0x12:
1202               case 0x13:
1203                 branch_pos = 3;
1204                 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                 if (old_offset == addr)
1211                     raddr++;
1212                 break;
1213 
1214               case 0x1e:
1215               case 0x1f:
1216                 branch_pos = 3;
1217                 raddr = 4;
1218                 break;
1219 
1220               case 0x18:
1221                 branch_pos = 4;
1222                 raddr = 5;
1223                 break;
1224 
1225               default:
1226                 branch_pos = 1;
1227                 raddr = 2;
1228                 break;
1229               }
1230             offset = bfd_get_8 (abfd, contents + irel->r_offset + branch_pos);
1231             raddr += old_offset;
1232             raddr += ((unsigned short) offset | ((offset & 0x80) ? 0xff00 : 0));
1233             if (irel->r_offset < addr && raddr > addr)
1234               {
1235                 offset -= count;
1236                 bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
1237               }
1238             else if (irel->r_offset >= addr && raddr <= addr)
1239               {
1240                 offset += count;
1241                 bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
1242               }
1243             else
1244               {
1245                 /*printf ("Not adjusted 0x%04x [0x%4x 0x%4x]\n", raddr,
1246                     irel->r_offset, addr);*/
1247               }
1248 
1249             break;
1250           }
1251     }
1252 
1253   /* Adjust the local symbols defined in this section.  */
1254   isymend = isymbuf + symtab_hdr->sh_info;
1255   for (isym = isymbuf; isym < isymend; isym++)
1256     {
1257       if (isym->st_shndx == sec_shndx
1258             && isym->st_value > addr
1259             && isym->st_value <= toaddr)
1260           isym->st_value -= count;
1261     }
1262 
1263   /* Now adjust the global symbols defined in this section.  */
1264   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1265                 - symtab_hdr->sh_info);
1266   sym_hashes = elf_sym_hashes (abfd);
1267   end_hashes = sym_hashes + symcount;
1268   for (; sym_hashes < end_hashes; sym_hashes++)
1269     {
1270       struct elf_link_hash_entry *sym_hash = *sym_hashes;
1271       if ((sym_hash->root.type == bfd_link_hash_defined
1272              || sym_hash->root.type == bfd_link_hash_defweak)
1273             && sym_hash->root.u.def.section == sec
1274             && sym_hash->root.u.def.value > addr
1275             && sym_hash->root.u.def.value <= toaddr)
1276           {
1277             sym_hash->root.u.def.value -= count;
1278           }
1279     }
1280 }
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"
1325