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