* elf32-m68hc11.c: Formatting fixes.
[external/binutils.git] / bfd / elf32-m68hc12.c
1 /* Motorola 68HC12-specific support for 32-bit ELF
2    Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
3    Contributed by Stephane Carrez (stcarrez@nerim.fr)
4    (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/m68hc11.h"
27 #include "opcode/m68hc11.h"
28
29 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
30   PARAMS ((bfd *, bfd_reloc_code_real_type));
31 static void m68hc11_info_to_howto_rel
32   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
33
34 static bfd_reloc_status_type m68hc11_elf_ignore_reloc
35   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
36 static bfd_reloc_status_type m68hc12_elf_special_reloc
37   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38 static int m68hc12_addr_is_banked PARAMS ((bfd_vma));
39 static bfd_vma m68hc12_phys_addr PARAMS ((bfd_vma));
40 static bfd_vma m68hc12_phys_page PARAMS ((bfd_vma));
41
42 /* GC mark and sweep.  */
43 static asection *elf32_m68hc11_gc_mark_hook
44   PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
45            struct elf_link_hash_entry *, Elf_Internal_Sym *));
46 static boolean elf32_m68hc11_gc_sweep_hook
47   PARAMS ((bfd *, struct bfd_link_info *, asection *,
48            const Elf_Internal_Rela *));
49
50 boolean _bfd_m68hc12_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
51 boolean _bfd_m68hc12_elf_set_private_flags PARAMS ((bfd *, flagword));
52 boolean _bfd_m68hc12_elf_print_private_bfd_data PARAMS ((bfd *, PTR));
53
54
55
56 /* Use REL instead of RELA to save space */
57 #define USE_REL
58
59 /* The Motorola 68HC11 microcontroler only addresses 64Kb.
60    We must handle 8 and 16-bit relocations.  The 32-bit relocation
61    is defined but not used except by gas when -gstabs is used (which
62    is wrong).
63
64    The 68HC12 microcontroler has a memory bank switching system
65    with a 16Kb window in the 64Kb address space.  The extended memory
66    is mapped in the 16Kb window (at 0x8000).  The page register controls
67    which 16Kb bank is mapped.  The call/rtc instructions take care of
68    bank switching in function calls/returns.
69
70    For GNU Binutils to work, we consider there is a physical memory
71    at 0..0x0ffff and a kind of virtual memory above that.  Symbols
72    in virtual memory have their addresses treated in a special way
73    when disassembling and when linking.
74
75    For the linker to work properly, we must always relocate the virtual
76    memory as if it is mapped at 0x8000.  When a 16-bit relocation is
77    made in the virtual memory, we check that it does not cross the
78    memory bank where it is used.  This would involve a page change
79    which would be wrong.  The 24-bit relocation is for that and it
80    treats the address as a physical address + page number.
81
82
83                                         Banked
84                                         Address Space
85                                         |               |       Page n
86                                         +---------------+ 0x1010000
87                                         |               |
88                                         | jsr _foo      |
89                                         | ..            |       Page 3
90                                         | _foo:         |
91                                         +---------------+ 0x100C000
92                                         |               |
93                                         | call _bar     |
94                                         | ..            |       Page 2
95                                         | _bar:         |
96                                         +---------------+ 0x1008000
97                                 /------>|               |
98                                 |       | call _foo     |       Page 1
99                                 |       |               |
100                                 |       +---------------+ 0x1004000
101       Physical                  |       |               |
102       Address Space             |       |               |       Page 0
103                                 |       |               |
104     +-----------+ 0x00FFFF      |       +---------------+ 0x1000000
105     |           |               |
106     | call _foo |               |
107     |           |               |
108     +-----------+ 0x00BFFF -+---/
109     |           |           |
110     |           |           |
111     |           | 16K       |
112     |           |           |
113     +-----------+ 0x008000 -+
114     |           |
115     |           |
116     =           =
117     |           |
118     |           |
119     +-----------+ 0000
120
121
122    The 'call _foo' must be relocated with page 3 and 16-bit address
123    mapped at 0x8000.  
124
125    The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
126 static reloc_howto_type elf_m68hc11_howto_table[] = {
127   /* This reloc does nothing.  */
128   HOWTO (R_M68HC11_NONE,        /* type */
129          0,                     /* rightshift */
130          2,                     /* size (0 = byte, 1 = short, 2 = long) */
131          32,                    /* bitsize */
132          false,                 /* pc_relative */
133          0,                     /* bitpos */
134          complain_overflow_dont,/* complain_on_overflow */
135          bfd_elf_generic_reloc, /* special_function */
136          "R_M68HC12_NONE",      /* name */
137          false,                 /* partial_inplace */
138          0,                     /* src_mask */
139          0,                     /* dst_mask */
140          false),                /* pcrel_offset */
141
142   /* A 8 bit absolute relocation */
143   HOWTO (R_M68HC11_8,           /* type */
144          0,                     /* rightshift */
145          0,                     /* size (0 = byte, 1 = short, 2 = long) */
146          8,                     /* bitsize */
147          false,                 /* pc_relative */
148          0,                     /* bitpos */
149          complain_overflow_bitfield,    /* complain_on_overflow */
150          bfd_elf_generic_reloc, /* special_function */
151          "R_M68HC12_8",         /* name */
152          false,                 /* partial_inplace */
153          0x00ff,                /* src_mask */
154          0x00ff,                /* dst_mask */
155          false),                /* pcrel_offset */
156
157   /* A 8 bit absolute relocation (upper address) */
158   HOWTO (R_M68HC11_HI8,         /* type */
159          8,                     /* rightshift */
160          0,                     /* size (0 = byte, 1 = short, 2 = long) */
161          8,                     /* bitsize */
162          false,                 /* pc_relative */
163          0,                     /* bitpos */
164          complain_overflow_bitfield,    /* complain_on_overflow */
165          bfd_elf_generic_reloc, /* special_function */
166          "R_M68HC12_HI8",       /* name */
167          false,                 /* partial_inplace */
168          0x00ff,                /* src_mask */
169          0x00ff,                /* dst_mask */
170          false),                /* pcrel_offset */
171
172   /* A 8 bit absolute relocation (upper address) */
173   HOWTO (R_M68HC11_LO8,         /* type */
174          0,                     /* rightshift */
175          0,                     /* size (0 = byte, 1 = short, 2 = long) */
176          8,                     /* bitsize */
177          false,                 /* pc_relative */
178          0,                     /* bitpos */
179          complain_overflow_dont,        /* complain_on_overflow */
180          bfd_elf_generic_reloc, /* special_function */
181          "R_M68HC12_LO8",       /* name */
182          false,                 /* partial_inplace */
183          0x00ff,                /* src_mask */
184          0x00ff,                /* dst_mask */
185          false),                /* pcrel_offset */
186
187   /* A 8 bit PC-rel relocation */
188   HOWTO (R_M68HC11_PCREL_8,     /* type */
189          0,                     /* rightshift */
190          0,                     /* size (0 = byte, 1 = short, 2 = long) */
191          8,                     /* bitsize */
192          true,                  /* pc_relative */
193          0,                     /* bitpos */
194          complain_overflow_bitfield,    /* complain_on_overflow */
195          bfd_elf_generic_reloc, /* special_function */
196          "R_M68HC12_PCREL_8",   /* name */
197          false,                 /* partial_inplace */
198          0x00ff,                /* src_mask */
199          0x00ff,                /* dst_mask */
200          false),                /* pcrel_offset */
201
202   /* A 16 bit absolute relocation */
203   HOWTO (R_M68HC11_16,          /* type */
204          0,                     /* rightshift */
205          1,                     /* size (0 = byte, 1 = short, 2 = long) */
206          16,                    /* bitsize */
207          false,                 /* pc_relative */
208          0,                     /* bitpos */
209          complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
210          m68hc12_elf_special_reloc,     /* special_function */
211          "R_M68HC12_16",        /* name */
212          false,                 /* partial_inplace */
213          0xffff,                /* src_mask */
214          0xffff,                /* dst_mask */
215          false),                /* pcrel_offset */
216
217   /* A 32 bit absolute relocation.  This one is never used for the
218      code relocation.  It's used by gas for -gstabs generation.  */
219   HOWTO (R_M68HC11_32,          /* type */
220          0,                     /* rightshift */
221          2,                     /* size (0 = byte, 1 = short, 2 = long) */
222          32,                    /* bitsize */
223          false,                 /* pc_relative */
224          0,                     /* bitpos */
225          complain_overflow_bitfield,    /* complain_on_overflow */
226          bfd_elf_generic_reloc, /* special_function */
227          "R_M68HC12_32",        /* name */
228          false,                 /* partial_inplace */
229          0xffffffff,            /* src_mask */
230          0xffffffff,            /* dst_mask */
231          false),                /* pcrel_offset */
232
233   /* A 3 bit absolute relocation */
234   HOWTO (R_M68HC11_3B,          /* type */
235          0,                     /* rightshift */
236          0,                     /* size (0 = byte, 1 = short, 2 = long) */
237          3,                     /* bitsize */
238          false,                 /* pc_relative */
239          0,                     /* bitpos */
240          complain_overflow_bitfield,    /* complain_on_overflow */
241          bfd_elf_generic_reloc, /* special_function */
242          "R_M68HC12_4B",        /* name */
243          false,                 /* partial_inplace */
244          0x003,                 /* src_mask */
245          0x003,                 /* dst_mask */
246          false),                /* pcrel_offset */
247
248   /* A 16 bit PC-rel relocation */
249   HOWTO (R_M68HC11_PCREL_16,    /* type */
250          0,                     /* rightshift */
251          1,                     /* size (0 = byte, 1 = short, 2 = long) */
252          16,                    /* bitsize */
253          true,                  /* pc_relative */
254          0,                     /* bitpos */
255          complain_overflow_dont,        /* complain_on_overflow */
256          bfd_elf_generic_reloc, /* special_function */
257          "R_M68HC12_PCREL_16",  /* name */
258          false,                 /* partial_inplace */
259          0xffff,                /* src_mask */
260          0xffff,                /* dst_mask */
261          false),                /* pcrel_offset */
262
263   /* GNU extension to record C++ vtable hierarchy */
264   HOWTO (R_M68HC11_GNU_VTINHERIT,       /* type */
265          0,                     /* rightshift */
266          1,                     /* size (0 = byte, 1 = short, 2 = long) */
267          0,                     /* bitsize */
268          false,                 /* pc_relative */
269          0,                     /* bitpos */
270          complain_overflow_dont,        /* complain_on_overflow */
271          NULL,                  /* special_function */
272          "R_M68HC11_GNU_VTINHERIT",     /* name */
273          false,                 /* partial_inplace */
274          0,                     /* src_mask */
275          0,                     /* dst_mask */
276          false),                /* pcrel_offset */
277
278   /* GNU extension to record C++ vtable member usage */
279   HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
280          0,                     /* rightshift */
281          1,                     /* size (0 = byte, 1 = short, 2 = long) */
282          0,                     /* bitsize */
283          false,                 /* pc_relative */
284          0,                     /* bitpos */
285          complain_overflow_dont,        /* complain_on_overflow */
286          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
287          "R_M68HC11_GNU_VTENTRY",       /* name */
288          false,                 /* partial_inplace */
289          0,                     /* src_mask */
290          0,                     /* dst_mask */
291          false),                /* pcrel_offset */
292
293   /* A 24 bit relocation */
294   HOWTO (R_M68HC11_24,          /* type */
295          0,                     /* rightshift */
296          1,                     /* size (0 = byte, 1 = short, 2 = long) */
297          24,                    /* bitsize */
298          false,                 /* pc_relative */
299          0,                     /* bitpos */
300          complain_overflow_dont,        /* complain_on_overflow */
301          m68hc12_elf_special_reloc,     /* special_function */
302          "R_M68HC12_24",        /* name */
303          false,                 /* partial_inplace */
304          0xffff,                /* src_mask */
305          0xffff,                /* dst_mask */
306          false),                /* pcrel_offset */
307   
308   /* A 16-bit low relocation */
309   HOWTO (R_M68HC11_LO16,        /* type */
310          0,                     /* rightshift */
311          1,                     /* size (0 = byte, 1 = short, 2 = long) */
312          16,                    /* bitsize */
313          false,                 /* pc_relative */
314          0,                     /* bitpos */
315          complain_overflow_dont,        /* complain_on_overflow */
316          m68hc12_elf_special_reloc,/* special_function */
317          "R_M68HC12_LO16",      /* name */
318          false,                 /* partial_inplace */
319          0xffff,                /* src_mask */
320          0xffff,                /* dst_mask */
321          false),                /* pcrel_offset */
322
323   /* A page relocation */
324   HOWTO (R_M68HC11_PAGE,        /* type */
325          0,                     /* rightshift */
326          0,                     /* size (0 = byte, 1 = short, 2 = long) */
327          8,                     /* bitsize */
328          false,                 /* pc_relative */
329          0,                     /* bitpos */
330          complain_overflow_dont,        /* complain_on_overflow */
331          m68hc12_elf_special_reloc,/* special_function */
332          "R_M68HC12_PAGE",      /* name */
333          false,                 /* partial_inplace */
334          0x00ff,                /* src_mask */
335          0x00ff,                /* dst_mask */
336          false),                /* pcrel_offset */
337
338   EMPTY_HOWTO (14),
339   EMPTY_HOWTO (15),
340   EMPTY_HOWTO (16),
341   EMPTY_HOWTO (17),
342   EMPTY_HOWTO (18),
343   EMPTY_HOWTO (19),
344   
345   /* Mark beginning of a jump instruction (any form).  */
346   HOWTO (R_M68HC11_RL_JUMP,     /* type */
347          0,                     /* rightshift */
348          1,                     /* size (0 = byte, 1 = short, 2 = long) */
349          0,                     /* bitsize */
350          false,                 /* pc_relative */
351          0,                     /* bitpos */
352          complain_overflow_dont,        /* complain_on_overflow */
353          m68hc11_elf_ignore_reloc,      /* special_function */
354          "R_M68HC12_RL_JUMP",   /* name */
355          true,                  /* partial_inplace */
356          0,                     /* src_mask */
357          0,                     /* dst_mask */
358          true),                 /* pcrel_offset */
359
360   /* Mark beginning of Gcc relaxation group instruction.  */
361   HOWTO (R_M68HC11_RL_GROUP,    /* type */
362          0,                     /* rightshift */
363          1,                     /* size (0 = byte, 1 = short, 2 = long) */
364          0,                     /* bitsize */
365          false,                 /* pc_relative */
366          0,                     /* bitpos */
367          complain_overflow_dont,        /* complain_on_overflow */
368          m68hc11_elf_ignore_reloc,      /* special_function */
369          "R_M68HC12_RL_GROUP",  /* name */
370          true,                  /* partial_inplace */
371          0,                     /* src_mask */
372          0,                     /* dst_mask */
373          true),                 /* pcrel_offset */
374 };
375
376 /* Map BFD reloc types to M68HC11 ELF reloc types.  */
377
378 struct m68hc11_reloc_map
379 {
380   bfd_reloc_code_real_type bfd_reloc_val;
381   unsigned char elf_reloc_val;
382 };
383
384 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
385   {BFD_RELOC_NONE, R_M68HC11_NONE,},
386   {BFD_RELOC_8, R_M68HC11_8},
387   {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
388   {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
389   {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
390   {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
391   {BFD_RELOC_16, R_M68HC11_16},
392   {BFD_RELOC_32, R_M68HC11_32},
393   {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
394
395   {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
396   {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
397
398   {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
399   {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
400   {BFD_RELOC_M68HC11_24, R_M68HC11_24},
401
402   {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
403   {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
404 };
405
406 static reloc_howto_type *
407 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
408      bfd *abfd ATTRIBUTE_UNUSED;
409      bfd_reloc_code_real_type code;
410 {
411   unsigned int i;
412
413   for (i = 0;
414        i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
415        i++)
416     {
417       if (m68hc11_reloc_map[i].bfd_reloc_val == code)
418         return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
419     }
420
421   return NULL;
422 }
423
424 /* This function is used for relocs which are only used for relaxing,
425    which the linker should otherwise ignore.  */
426
427 static bfd_reloc_status_type
428 m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
429                           output_bfd, error_message)
430      bfd *abfd ATTRIBUTE_UNUSED;
431      arelent *reloc_entry;
432      asymbol *symbol ATTRIBUTE_UNUSED;
433      PTR data ATTRIBUTE_UNUSED;
434      asection *input_section;
435      bfd *output_bfd;
436      char **error_message ATTRIBUTE_UNUSED;
437 {
438   if (output_bfd != NULL)
439     reloc_entry->address += input_section->output_offset;
440   return bfd_reloc_ok;
441 }
442
443 static int
444 m68hc12_addr_is_banked (addr)
445      bfd_vma addr;
446 {
447    return (addr >= M68HC12_BANK_VIRT) ? 1 : 0;
448 }
449
450 /* Return the physical address seen by the processor, taking
451    into account banked memory.  */
452 static bfd_vma
453 m68hc12_phys_addr (addr)
454      bfd_vma addr;
455 {
456   if (addr < M68HC12_BANK_VIRT)
457     return addr;
458
459   /* Map the address to the memory bank.  */
460   addr -= M68HC12_BANK_VIRT;
461   addr &= M68HC12_BANK_MASK;
462   addr += M68HC12_BANK_BASE;
463   return addr;
464 }
465
466 /* Return the page number corresponding to an address in banked memory.  */
467 static bfd_vma
468 m68hc12_phys_page (addr)
469      bfd_vma addr;
470 {
471   if (addr < M68HC12_BANK_VIRT)
472     return 0;
473
474   /* Map the address to the memory bank.  */
475   addr -= M68HC12_BANK_VIRT;
476   addr >>= M68HC12_BANK_SHIFT;
477   addr &= M68HC12_BANK_PAGE_MASK;
478   return addr;
479 }
480
481 static bfd_reloc_status_type
482 m68hc12_elf_special_reloc (abfd, reloc_entry, symbol, data, input_section,
483                            output_bfd, error_message)
484      bfd *abfd;
485      arelent *reloc_entry;
486      asymbol *symbol;
487      PTR data;
488      asection *input_section;
489      bfd *output_bfd;
490      char **error_message ATTRIBUTE_UNUSED;
491 {
492   reloc_howto_type *howto;
493   bfd_vma relocation;
494   bfd_vma phys_addr;
495   bfd_vma phys_page;
496   bfd_vma insn_page;
497   bfd_vma insn_addr;
498   
499   if (output_bfd != (bfd *) NULL
500       && (symbol->flags & BSF_SECTION_SYM) == 0
501       && (! reloc_entry->howto->partial_inplace
502           || reloc_entry->addend == 0))
503     {
504       reloc_entry->address += input_section->output_offset;
505       return bfd_reloc_ok;
506     }
507
508   if (output_bfd != NULL)
509     return bfd_reloc_continue;
510
511   if (reloc_entry->address > input_section->_cooked_size)
512     return bfd_reloc_outofrange;
513
514   /* Compute relocation.  */
515   relocation = (symbol->value
516                 + symbol->section->output_section->vma
517                 + symbol->section->output_offset);
518   relocation += reloc_entry->addend;
519   relocation += bfd_get_16 (abfd, (bfd_byte*) data + reloc_entry->address);
520
521   /* Do the memory bank mapping.  */
522   phys_addr = m68hc12_phys_addr (relocation);
523   phys_page = m68hc12_phys_page (relocation);
524
525   howto = reloc_entry->howto;
526   if (howto->complain_on_overflow != complain_overflow_dont
527       && (phys_addr & (((bfd_vma) -1) << 16)))
528      return bfd_reloc_overflow;
529
530   switch (howto->type)
531     {
532     case R_M68HC11_16:
533           /* Get virtual address of instruction having the relocation.  */
534        insn_addr = input_section->output_section->vma
535           + input_section->output_offset
536           + reloc_entry->address;
537
538       insn_page = m68hc12_phys_page (insn_addr);
539
540       if (m68hc12_addr_is_banked (relocation)
541           && m68hc12_addr_is_banked (insn_addr)
542           && phys_page != insn_page)
543          {
544             *error_message = _("address is not in the same bank");
545             return bfd_reloc_dangerous;
546          }
547       if (m68hc12_addr_is_banked (relocation)
548           && !m68hc12_addr_is_banked (insn_addr))
549          {
550             *error_message = _("reference to a banked address in "
551                                "the normal address space");
552             return bfd_reloc_dangerous;
553          }
554       
555     case R_M68HC11_LO16:
556       bfd_put_16 (abfd, phys_addr, (bfd_byte*) data + reloc_entry->address);
557       break;
558
559     case R_M68HC11_24:
560       bfd_put_16 (abfd, phys_addr, (bfd_byte*) data + reloc_entry->address);
561       bfd_put_8 (abfd, phys_page, (bfd_byte*) data + reloc_entry->address + 2);
562       break;
563
564     case R_M68HC11_PAGE:
565       bfd_put_8 (abfd, phys_page, (bfd_byte*) data + reloc_entry->address);
566       break;
567
568     default:
569        abort ();
570        break;
571     }
572   
573   return bfd_reloc_ok;
574 }
575
576 /* Set the howto pointer for an M68HC11 ELF reloc.  */
577
578 static void
579 m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
580      bfd *abfd ATTRIBUTE_UNUSED;
581      arelent *cache_ptr;
582      Elf32_Internal_Rel *dst;
583 {
584   unsigned int r_type;
585
586   r_type = ELF32_R_TYPE (dst->r_info);
587   BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
588   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
589 }
590
591 static asection *
592 elf32_m68hc11_gc_mark_hook (sec, info, rel, h, sym)
593      asection *sec;
594      struct bfd_link_info *info ATTRIBUTE_UNUSED;
595      Elf_Internal_Rela *rel;
596      struct elf_link_hash_entry *h;
597      Elf_Internal_Sym *sym;
598 {
599   if (h != NULL)
600     {
601       switch (ELF32_R_TYPE (rel->r_info))
602         {
603         default:
604           switch (h->root.type)
605             {
606             case bfd_link_hash_defined:
607             case bfd_link_hash_defweak:
608               return h->root.u.def.section;
609
610             case bfd_link_hash_common:
611               return h->root.u.c.p->section;
612
613             default:
614               break;
615             }
616         }
617     }
618   else
619     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
620
621   return NULL;
622 }
623
624 static boolean
625 elf32_m68hc11_gc_sweep_hook (abfd, info, sec, relocs)
626      bfd *abfd ATTRIBUTE_UNUSED;
627      struct bfd_link_info *info ATTRIBUTE_UNUSED;
628      asection *sec ATTRIBUTE_UNUSED;
629      const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
630 {
631   /* We don't use got and plt entries for 68hc11/68hc12.  */
632   return true;
633 }
634
635 \f
636 /* Set and control ELF flags in ELF header.  */
637
638 boolean
639 _bfd_m68hc12_elf_set_private_flags (abfd, flags)
640      bfd *abfd;
641      flagword flags;
642 {
643   BFD_ASSERT (!elf_flags_init (abfd)
644               || elf_elfheader (abfd)->e_flags == flags);
645
646   elf_elfheader (abfd)->e_flags = flags;
647   elf_flags_init (abfd) = true;
648   return true;
649 }
650
651 /* Merge backend specific data from an object file to the output
652    object file when linking.  */
653
654 boolean
655 _bfd_m68hc12_elf_merge_private_bfd_data (ibfd, obfd)
656      bfd *ibfd;
657      bfd *obfd;
658 {
659   flagword old_flags;
660   flagword new_flags;
661   boolean ok = true;
662
663   /* Check if we have the same endianess */
664   if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
665     return false;
666
667   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
668       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
669     return true;
670
671   new_flags = elf_elfheader (ibfd)->e_flags;
672   elf_elfheader (obfd)->e_flags |= new_flags & EF_M68HC11_ABI;
673   old_flags = elf_elfheader (obfd)->e_flags;
674
675   if (! elf_flags_init (obfd))
676     {
677       elf_flags_init (obfd) = true;
678       elf_elfheader (obfd)->e_flags = new_flags;
679       elf_elfheader (obfd)->e_ident[EI_CLASS]
680         = elf_elfheader (ibfd)->e_ident[EI_CLASS];
681
682       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
683           && bfd_get_arch_info (obfd)->the_default)
684         {
685           if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
686                                    bfd_get_mach (ibfd)))
687             return false;
688         }
689
690       return true;
691     }
692
693   /* Check ABI compatibility.  */
694   if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
695     {
696       (*_bfd_error_handler)
697         (_("%s: linking files compiled for 16-bit integers (-mshort) "
698            "and others for 32-bit integers"),
699          bfd_archive_filename (ibfd));
700       ok = false;
701     }
702   if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
703     {
704       (*_bfd_error_handler)
705         (_("%s: linking files compiled for 32-bit double (-fshort-double) "
706            "and others for 64-bit double"),
707          bfd_archive_filename (ibfd));
708       ok = false;
709     }
710   new_flags &= ~EF_M68HC11_ABI;
711   old_flags &= ~EF_M68HC11_ABI;
712
713   /* Warn about any other mismatches */
714   if (new_flags != old_flags)
715     {
716       (*_bfd_error_handler)
717         (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
718          bfd_archive_filename (ibfd), (unsigned long) new_flags,
719          (unsigned long) old_flags);
720       ok = false;
721     }
722
723   if (! ok)
724     {
725       bfd_set_error (bfd_error_bad_value);
726       return false;
727     }
728
729   return true;
730 }
731
732 boolean
733 _bfd_m68hc12_elf_print_private_bfd_data (abfd, ptr)
734      bfd *abfd;
735      PTR ptr;
736 {
737   FILE *file = (FILE *) ptr;
738
739   BFD_ASSERT (abfd != NULL && ptr != NULL);
740
741   /* Print normal ELF private data.  */
742   _bfd_elf_print_private_bfd_data (abfd, ptr);
743
744   /* xgettext:c-format */
745   fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
746
747   if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
748     fprintf (file, _("[abi=32-bit int,"));
749   else
750     fprintf (file, _("[abi=16-bit int,"));
751
752   if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
753     fprintf (file, _(" 64-bit double]"));
754   else
755     fprintf (file, _(" 32-bit double]"));
756
757   fputc ('\n', file);
758
759   return true;
760 }
761
762 /* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
763    The Motorola spec says to use a different Elf machine code.  */
764 #define ELF_ARCH                bfd_arch_m68hc12
765 #define ELF_MACHINE_CODE        EM_68HC12
766 #define ELF_MAXPAGESIZE         0x1000
767
768 #define TARGET_BIG_SYM          bfd_elf32_m68hc12_vec
769 #define TARGET_BIG_NAME         "elf32-m68hc12"
770
771 #define elf_info_to_howto       0
772 #define elf_info_to_howto_rel   m68hc11_info_to_howto_rel
773 #define elf_backend_gc_mark_hook     elf32_m68hc11_gc_mark_hook
774 #define elf_backend_gc_sweep_hook    elf32_m68hc11_gc_sweep_hook
775 #define elf_backend_object_p    0
776 #define elf_backend_final_write_processing      0
777 /* Disabled as this backend uses the generic linker.  */
778 #define elf_backend_can_gc_sections             0
779
780 #define bfd_elf32_bfd_merge_private_bfd_data \
781                                         _bfd_m68hc12_elf_merge_private_bfd_data
782 #define bfd_elf32_bfd_set_private_flags _bfd_m68hc12_elf_set_private_flags
783 #define bfd_elf32_bfd_print_private_bfd_data \
784                                         _bfd_m68hc12_elf_print_private_bfd_data
785
786 #include "elf32-target.h"