1*3d8817e4Smiod /* Motorola 68HC11/HC12-specific support for 32-bit ELF
2*3d8817e4Smiod    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
3*3d8817e4Smiod    Free Software Foundation, Inc.
4*3d8817e4Smiod    Contributed by Stephane Carrez (stcarrez@nerim.fr)
5*3d8817e4Smiod 
6*3d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
7*3d8817e4Smiod 
8*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
9*3d8817e4Smiod it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
11*3d8817e4Smiod (at your option) any later version.
12*3d8817e4Smiod 
13*3d8817e4Smiod This program is distributed in the hope that it will be useful,
14*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*3d8817e4Smiod GNU General Public License for more details.
17*3d8817e4Smiod 
18*3d8817e4Smiod You should have received a copy of the GNU General Public License
19*3d8817e4Smiod along with this program; if not, write to the Free Software
20*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
21*3d8817e4Smiod 
22*3d8817e4Smiod #include "bfd.h"
23*3d8817e4Smiod #include "sysdep.h"
24*3d8817e4Smiod #include "bfdlink.h"
25*3d8817e4Smiod #include "libbfd.h"
26*3d8817e4Smiod #include "elf-bfd.h"
27*3d8817e4Smiod #include "elf32-m68hc1x.h"
28*3d8817e4Smiod #include "elf/m68hc11.h"
29*3d8817e4Smiod #include "opcode/m68hc11.h"
30*3d8817e4Smiod 
31*3d8817e4Smiod 
32*3d8817e4Smiod #define m68hc12_stub_hash_lookup(table, string, create, copy) \
33*3d8817e4Smiod   ((struct elf32_m68hc11_stub_hash_entry *) \
34*3d8817e4Smiod    bfd_hash_lookup ((table), (string), (create), (copy)))
35*3d8817e4Smiod 
36*3d8817e4Smiod static struct elf32_m68hc11_stub_hash_entry* m68hc12_add_stub
37*3d8817e4Smiod   (const char *stub_name,
38*3d8817e4Smiod    asection *section,
39*3d8817e4Smiod    struct m68hc11_elf_link_hash_table *htab);
40*3d8817e4Smiod 
41*3d8817e4Smiod static struct bfd_hash_entry *stub_hash_newfunc
42*3d8817e4Smiod   (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
43*3d8817e4Smiod 
44*3d8817e4Smiod static void m68hc11_elf_set_symbol (bfd* abfd, struct bfd_link_info *info,
45*3d8817e4Smiod                                     const char* name, bfd_vma value,
46*3d8817e4Smiod                                     asection* sec);
47*3d8817e4Smiod 
48*3d8817e4Smiod static bfd_boolean m68hc11_elf_export_one_stub
49*3d8817e4Smiod   (struct bfd_hash_entry *gen_entry, void *in_arg);
50*3d8817e4Smiod 
51*3d8817e4Smiod static void scan_sections_for_abi (bfd*, asection*, PTR);
52*3d8817e4Smiod 
53*3d8817e4Smiod struct m68hc11_scan_param
54*3d8817e4Smiod {
55*3d8817e4Smiod    struct m68hc11_page_info* pinfo;
56*3d8817e4Smiod    bfd_boolean use_memory_banks;
57*3d8817e4Smiod };
58*3d8817e4Smiod 
59*3d8817e4Smiod 
60*3d8817e4Smiod /* Create a 68HC11/68HC12 ELF linker hash table.  */
61*3d8817e4Smiod 
62*3d8817e4Smiod struct m68hc11_elf_link_hash_table*
m68hc11_elf_hash_table_create(bfd * abfd)63*3d8817e4Smiod m68hc11_elf_hash_table_create (bfd *abfd)
64*3d8817e4Smiod {
65*3d8817e4Smiod   struct m68hc11_elf_link_hash_table *ret;
66*3d8817e4Smiod   bfd_size_type amt = sizeof (struct m68hc11_elf_link_hash_table);
67*3d8817e4Smiod 
68*3d8817e4Smiod   ret = (struct m68hc11_elf_link_hash_table *) bfd_malloc (amt);
69*3d8817e4Smiod   if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
70*3d8817e4Smiod     return NULL;
71*3d8817e4Smiod 
72*3d8817e4Smiod   memset (ret, 0, amt);
73*3d8817e4Smiod   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
74*3d8817e4Smiod 				      _bfd_elf_link_hash_newfunc,
75*3d8817e4Smiod 				      sizeof (struct elf_link_hash_entry)))
76*3d8817e4Smiod     {
77*3d8817e4Smiod       free (ret);
78*3d8817e4Smiod       return NULL;
79*3d8817e4Smiod     }
80*3d8817e4Smiod 
81*3d8817e4Smiod   /* Init the stub hash table too.  */
82*3d8817e4Smiod   amt = sizeof (struct bfd_hash_table);
83*3d8817e4Smiod   ret->stub_hash_table = (struct bfd_hash_table*) bfd_malloc (amt);
84*3d8817e4Smiod   if (ret->stub_hash_table == NULL)
85*3d8817e4Smiod     {
86*3d8817e4Smiod       free (ret);
87*3d8817e4Smiod       return NULL;
88*3d8817e4Smiod     }
89*3d8817e4Smiod   if (!bfd_hash_table_init (ret->stub_hash_table, stub_hash_newfunc,
90*3d8817e4Smiod 			    sizeof (struct elf32_m68hc11_stub_hash_entry)))
91*3d8817e4Smiod     return NULL;
92*3d8817e4Smiod 
93*3d8817e4Smiod   ret->stub_bfd = NULL;
94*3d8817e4Smiod   ret->stub_section = 0;
95*3d8817e4Smiod   ret->add_stub_section = NULL;
96*3d8817e4Smiod   ret->sym_sec.abfd = NULL;
97*3d8817e4Smiod 
98*3d8817e4Smiod   return ret;
99*3d8817e4Smiod }
100*3d8817e4Smiod 
101*3d8817e4Smiod /* Free the derived linker hash table.  */
102*3d8817e4Smiod 
103*3d8817e4Smiod void
m68hc11_elf_bfd_link_hash_table_free(struct bfd_link_hash_table * hash)104*3d8817e4Smiod m68hc11_elf_bfd_link_hash_table_free (struct bfd_link_hash_table *hash)
105*3d8817e4Smiod {
106*3d8817e4Smiod   struct m68hc11_elf_link_hash_table *ret
107*3d8817e4Smiod     = (struct m68hc11_elf_link_hash_table *) hash;
108*3d8817e4Smiod 
109*3d8817e4Smiod   bfd_hash_table_free (ret->stub_hash_table);
110*3d8817e4Smiod   free (ret->stub_hash_table);
111*3d8817e4Smiod   _bfd_generic_link_hash_table_free (hash);
112*3d8817e4Smiod }
113*3d8817e4Smiod 
114*3d8817e4Smiod /* Assorted hash table functions.  */
115*3d8817e4Smiod 
116*3d8817e4Smiod /* Initialize an entry in the stub hash table.  */
117*3d8817e4Smiod 
118*3d8817e4Smiod static struct bfd_hash_entry *
stub_hash_newfunc(struct bfd_hash_entry * entry,struct bfd_hash_table * table,const char * string)119*3d8817e4Smiod stub_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table,
120*3d8817e4Smiod                    const char *string)
121*3d8817e4Smiod {
122*3d8817e4Smiod   /* Allocate the structure if it has not already been allocated by a
123*3d8817e4Smiod      subclass.  */
124*3d8817e4Smiod   if (entry == NULL)
125*3d8817e4Smiod     {
126*3d8817e4Smiod       entry = bfd_hash_allocate (table,
127*3d8817e4Smiod 				 sizeof (struct elf32_m68hc11_stub_hash_entry));
128*3d8817e4Smiod       if (entry == NULL)
129*3d8817e4Smiod 	return entry;
130*3d8817e4Smiod     }
131*3d8817e4Smiod 
132*3d8817e4Smiod   /* Call the allocation method of the superclass.  */
133*3d8817e4Smiod   entry = bfd_hash_newfunc (entry, table, string);
134*3d8817e4Smiod   if (entry != NULL)
135*3d8817e4Smiod     {
136*3d8817e4Smiod       struct elf32_m68hc11_stub_hash_entry *eh;
137*3d8817e4Smiod 
138*3d8817e4Smiod       /* Initialize the local fields.  */
139*3d8817e4Smiod       eh = (struct elf32_m68hc11_stub_hash_entry *) entry;
140*3d8817e4Smiod       eh->stub_sec = NULL;
141*3d8817e4Smiod       eh->stub_offset = 0;
142*3d8817e4Smiod       eh->target_value = 0;
143*3d8817e4Smiod       eh->target_section = NULL;
144*3d8817e4Smiod     }
145*3d8817e4Smiod 
146*3d8817e4Smiod   return entry;
147*3d8817e4Smiod }
148*3d8817e4Smiod 
149*3d8817e4Smiod /* Add a new stub entry to the stub hash.  Not all fields of the new
150*3d8817e4Smiod    stub entry are initialised.  */
151*3d8817e4Smiod 
152*3d8817e4Smiod static struct elf32_m68hc11_stub_hash_entry *
m68hc12_add_stub(const char * stub_name,asection * section,struct m68hc11_elf_link_hash_table * htab)153*3d8817e4Smiod m68hc12_add_stub (const char *stub_name, asection *section,
154*3d8817e4Smiod                   struct m68hc11_elf_link_hash_table *htab)
155*3d8817e4Smiod {
156*3d8817e4Smiod   struct elf32_m68hc11_stub_hash_entry *stub_entry;
157*3d8817e4Smiod 
158*3d8817e4Smiod   /* Enter this entry into the linker stub hash table.  */
159*3d8817e4Smiod   stub_entry = m68hc12_stub_hash_lookup (htab->stub_hash_table, stub_name,
160*3d8817e4Smiod                                          TRUE, FALSE);
161*3d8817e4Smiod   if (stub_entry == NULL)
162*3d8817e4Smiod     {
163*3d8817e4Smiod       (*_bfd_error_handler) (_("%B: cannot create stub entry %s"),
164*3d8817e4Smiod 			     section->owner, stub_name);
165*3d8817e4Smiod       return NULL;
166*3d8817e4Smiod     }
167*3d8817e4Smiod 
168*3d8817e4Smiod   if (htab->stub_section == 0)
169*3d8817e4Smiod     {
170*3d8817e4Smiod       htab->stub_section = (*htab->add_stub_section) (".tramp",
171*3d8817e4Smiod                                                       htab->tramp_section);
172*3d8817e4Smiod     }
173*3d8817e4Smiod 
174*3d8817e4Smiod   stub_entry->stub_sec = htab->stub_section;
175*3d8817e4Smiod   stub_entry->stub_offset = 0;
176*3d8817e4Smiod   return stub_entry;
177*3d8817e4Smiod }
178*3d8817e4Smiod 
179*3d8817e4Smiod /* Hook called by the linker routine which adds symbols from an object
180*3d8817e4Smiod    file.  We use it for identify far symbols and force a loading of
181*3d8817e4Smiod    the trampoline handler.  */
182*3d8817e4Smiod 
183*3d8817e4Smiod bfd_boolean
elf32_m68hc11_add_symbol_hook(bfd * abfd,struct bfd_link_info * info,Elf_Internal_Sym * sym,const char ** namep ATTRIBUTE_UNUSED,flagword * flagsp ATTRIBUTE_UNUSED,asection ** secp ATTRIBUTE_UNUSED,bfd_vma * valp ATTRIBUTE_UNUSED)184*3d8817e4Smiod elf32_m68hc11_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
185*3d8817e4Smiod                                Elf_Internal_Sym *sym,
186*3d8817e4Smiod                                const char **namep ATTRIBUTE_UNUSED,
187*3d8817e4Smiod                                flagword *flagsp ATTRIBUTE_UNUSED,
188*3d8817e4Smiod                                asection **secp ATTRIBUTE_UNUSED,
189*3d8817e4Smiod                                bfd_vma *valp ATTRIBUTE_UNUSED)
190*3d8817e4Smiod {
191*3d8817e4Smiod   if (sym->st_other & STO_M68HC12_FAR)
192*3d8817e4Smiod     {
193*3d8817e4Smiod       struct elf_link_hash_entry *h;
194*3d8817e4Smiod 
195*3d8817e4Smiod       h = (struct elf_link_hash_entry *)
196*3d8817e4Smiod 	bfd_link_hash_lookup (info->hash, "__far_trampoline",
197*3d8817e4Smiod                               FALSE, FALSE, FALSE);
198*3d8817e4Smiod       if (h == NULL)
199*3d8817e4Smiod         {
200*3d8817e4Smiod           struct bfd_link_hash_entry* entry = NULL;
201*3d8817e4Smiod 
202*3d8817e4Smiod           _bfd_generic_link_add_one_symbol (info, abfd,
203*3d8817e4Smiod                                             "__far_trampoline",
204*3d8817e4Smiod                                             BSF_GLOBAL,
205*3d8817e4Smiod                                             bfd_und_section_ptr,
206*3d8817e4Smiod                                             (bfd_vma) 0, (const char*) NULL,
207*3d8817e4Smiod                                             FALSE, FALSE, &entry);
208*3d8817e4Smiod         }
209*3d8817e4Smiod 
210*3d8817e4Smiod     }
211*3d8817e4Smiod   return TRUE;
212*3d8817e4Smiod }
213*3d8817e4Smiod 
214*3d8817e4Smiod /* External entry points for sizing and building linker stubs.  */
215*3d8817e4Smiod 
216*3d8817e4Smiod /* Set up various things so that we can make a list of input sections
217*3d8817e4Smiod    for each output section included in the link.  Returns -1 on error,
218*3d8817e4Smiod    0 when no stubs will be needed, and 1 on success.  */
219*3d8817e4Smiod 
220*3d8817e4Smiod int
elf32_m68hc11_setup_section_lists(bfd * output_bfd,struct bfd_link_info * info)221*3d8817e4Smiod elf32_m68hc11_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info)
222*3d8817e4Smiod {
223*3d8817e4Smiod   bfd *input_bfd;
224*3d8817e4Smiod   unsigned int bfd_count;
225*3d8817e4Smiod   int top_id, top_index;
226*3d8817e4Smiod   asection *section;
227*3d8817e4Smiod   asection **input_list, **list;
228*3d8817e4Smiod   bfd_size_type amt;
229*3d8817e4Smiod   asection *text_section;
230*3d8817e4Smiod   struct m68hc11_elf_link_hash_table *htab;
231*3d8817e4Smiod 
232*3d8817e4Smiod   htab = m68hc11_elf_hash_table (info);
233*3d8817e4Smiod 
234*3d8817e4Smiod   if (htab->root.root.creator->flavour != bfd_target_elf_flavour)
235*3d8817e4Smiod     return 0;
236*3d8817e4Smiod 
237*3d8817e4Smiod   /* Count the number of input BFDs and find the top input section id.
238*3d8817e4Smiod      Also search for an existing ".tramp" section so that we know
239*3d8817e4Smiod      where generated trampolines must go.  Default to ".text" if we
240*3d8817e4Smiod      can't find it.  */
241*3d8817e4Smiod   htab->tramp_section = 0;
242*3d8817e4Smiod   text_section = 0;
243*3d8817e4Smiod   for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
244*3d8817e4Smiod        input_bfd != NULL;
245*3d8817e4Smiod        input_bfd = input_bfd->link_next)
246*3d8817e4Smiod     {
247*3d8817e4Smiod       bfd_count += 1;
248*3d8817e4Smiod       for (section = input_bfd->sections;
249*3d8817e4Smiod 	   section != NULL;
250*3d8817e4Smiod 	   section = section->next)
251*3d8817e4Smiod 	{
252*3d8817e4Smiod           const char* name = bfd_get_section_name (input_bfd, section);
253*3d8817e4Smiod 
254*3d8817e4Smiod           if (!strcmp (name, ".tramp"))
255*3d8817e4Smiod             htab->tramp_section = section;
256*3d8817e4Smiod 
257*3d8817e4Smiod           if (!strcmp (name, ".text"))
258*3d8817e4Smiod             text_section = section;
259*3d8817e4Smiod 
260*3d8817e4Smiod 	  if (top_id < section->id)
261*3d8817e4Smiod 	    top_id = section->id;
262*3d8817e4Smiod 	}
263*3d8817e4Smiod     }
264*3d8817e4Smiod   htab->bfd_count = bfd_count;
265*3d8817e4Smiod   if (htab->tramp_section == 0)
266*3d8817e4Smiod     htab->tramp_section = text_section;
267*3d8817e4Smiod 
268*3d8817e4Smiod   /* We can't use output_bfd->section_count here to find the top output
269*3d8817e4Smiod      section index as some sections may have been removed, and
270*3d8817e4Smiod      strip_excluded_output_sections doesn't renumber the indices.  */
271*3d8817e4Smiod   for (section = output_bfd->sections, top_index = 0;
272*3d8817e4Smiod        section != NULL;
273*3d8817e4Smiod        section = section->next)
274*3d8817e4Smiod     {
275*3d8817e4Smiod       if (top_index < section->index)
276*3d8817e4Smiod 	top_index = section->index;
277*3d8817e4Smiod     }
278*3d8817e4Smiod 
279*3d8817e4Smiod   htab->top_index = top_index;
280*3d8817e4Smiod   amt = sizeof (asection *) * (top_index + 1);
281*3d8817e4Smiod   input_list = (asection **) bfd_malloc (amt);
282*3d8817e4Smiod   htab->input_list = input_list;
283*3d8817e4Smiod   if (input_list == NULL)
284*3d8817e4Smiod     return -1;
285*3d8817e4Smiod 
286*3d8817e4Smiod   /* For sections we aren't interested in, mark their entries with a
287*3d8817e4Smiod      value we can check later.  */
288*3d8817e4Smiod   list = input_list + top_index;
289*3d8817e4Smiod   do
290*3d8817e4Smiod     *list = bfd_abs_section_ptr;
291*3d8817e4Smiod   while (list-- != input_list);
292*3d8817e4Smiod 
293*3d8817e4Smiod   for (section = output_bfd->sections;
294*3d8817e4Smiod        section != NULL;
295*3d8817e4Smiod        section = section->next)
296*3d8817e4Smiod     {
297*3d8817e4Smiod       if ((section->flags & SEC_CODE) != 0)
298*3d8817e4Smiod 	input_list[section->index] = NULL;
299*3d8817e4Smiod     }
300*3d8817e4Smiod 
301*3d8817e4Smiod   return 1;
302*3d8817e4Smiod }
303*3d8817e4Smiod 
304*3d8817e4Smiod /* Determine and set the size of the stub section for a final link.
305*3d8817e4Smiod 
306*3d8817e4Smiod    The basic idea here is to examine all the relocations looking for
307*3d8817e4Smiod    PC-relative calls to a target that is unreachable with a "bl"
308*3d8817e4Smiod    instruction.  */
309*3d8817e4Smiod 
310*3d8817e4Smiod bfd_boolean
elf32_m68hc11_size_stubs(bfd * output_bfd,bfd * stub_bfd,struct bfd_link_info * info,asection * (* add_stub_section)(const char *,asection *))311*3d8817e4Smiod elf32_m68hc11_size_stubs (bfd *output_bfd, bfd *stub_bfd,
312*3d8817e4Smiod                           struct bfd_link_info *info,
313*3d8817e4Smiod                           asection * (*add_stub_section) (const char*, asection*))
314*3d8817e4Smiod {
315*3d8817e4Smiod   bfd *input_bfd;
316*3d8817e4Smiod   asection *section;
317*3d8817e4Smiod   Elf_Internal_Sym *local_syms, **all_local_syms;
318*3d8817e4Smiod   unsigned int bfd_indx, bfd_count;
319*3d8817e4Smiod   bfd_size_type amt;
320*3d8817e4Smiod   asection *stub_sec;
321*3d8817e4Smiod 
322*3d8817e4Smiod   struct m68hc11_elf_link_hash_table *htab = m68hc11_elf_hash_table (info);
323*3d8817e4Smiod 
324*3d8817e4Smiod   /* Stash our params away.  */
325*3d8817e4Smiod   htab->stub_bfd = stub_bfd;
326*3d8817e4Smiod   htab->add_stub_section = add_stub_section;
327*3d8817e4Smiod 
328*3d8817e4Smiod   /* Count the number of input BFDs and find the top input section id.  */
329*3d8817e4Smiod   for (input_bfd = info->input_bfds, bfd_count = 0;
330*3d8817e4Smiod        input_bfd != NULL;
331*3d8817e4Smiod        input_bfd = input_bfd->link_next)
332*3d8817e4Smiod     {
333*3d8817e4Smiod       bfd_count += 1;
334*3d8817e4Smiod     }
335*3d8817e4Smiod 
336*3d8817e4Smiod   /* We want to read in symbol extension records only once.  To do this
337*3d8817e4Smiod      we need to read in the local symbols in parallel and save them for
338*3d8817e4Smiod      later use; so hold pointers to the local symbols in an array.  */
339*3d8817e4Smiod   amt = sizeof (Elf_Internal_Sym *) * bfd_count;
340*3d8817e4Smiod   all_local_syms = (Elf_Internal_Sym **) bfd_zmalloc (amt);
341*3d8817e4Smiod   if (all_local_syms == NULL)
342*3d8817e4Smiod     return FALSE;
343*3d8817e4Smiod 
344*3d8817e4Smiod   /* Walk over all the input BFDs, swapping in local symbols.  */
345*3d8817e4Smiod   for (input_bfd = info->input_bfds, bfd_indx = 0;
346*3d8817e4Smiod        input_bfd != NULL;
347*3d8817e4Smiod        input_bfd = input_bfd->link_next, bfd_indx++)
348*3d8817e4Smiod     {
349*3d8817e4Smiod       Elf_Internal_Shdr *symtab_hdr;
350*3d8817e4Smiod 
351*3d8817e4Smiod       /* We'll need the symbol table in a second.  */
352*3d8817e4Smiod       symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
353*3d8817e4Smiod       if (symtab_hdr->sh_info == 0)
354*3d8817e4Smiod 	continue;
355*3d8817e4Smiod 
356*3d8817e4Smiod       /* We need an array of the local symbols attached to the input bfd.  */
357*3d8817e4Smiod       local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
358*3d8817e4Smiod       if (local_syms == NULL)
359*3d8817e4Smiod 	{
360*3d8817e4Smiod 	  local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
361*3d8817e4Smiod 					     symtab_hdr->sh_info, 0,
362*3d8817e4Smiod 					     NULL, NULL, NULL);
363*3d8817e4Smiod 	  /* Cache them for elf_link_input_bfd.  */
364*3d8817e4Smiod 	  symtab_hdr->contents = (unsigned char *) local_syms;
365*3d8817e4Smiod 	}
366*3d8817e4Smiod       if (local_syms == NULL)
367*3d8817e4Smiod         {
368*3d8817e4Smiod           free (all_local_syms);
369*3d8817e4Smiod 	  return FALSE;
370*3d8817e4Smiod         }
371*3d8817e4Smiod 
372*3d8817e4Smiod       all_local_syms[bfd_indx] = local_syms;
373*3d8817e4Smiod     }
374*3d8817e4Smiod 
375*3d8817e4Smiod   for (input_bfd = info->input_bfds, bfd_indx = 0;
376*3d8817e4Smiod        input_bfd != NULL;
377*3d8817e4Smiod        input_bfd = input_bfd->link_next, bfd_indx++)
378*3d8817e4Smiod     {
379*3d8817e4Smiod       Elf_Internal_Shdr *symtab_hdr;
380*3d8817e4Smiod       Elf_Internal_Sym *local_syms;
381*3d8817e4Smiod       struct elf_link_hash_entry ** sym_hashes;
382*3d8817e4Smiod 
383*3d8817e4Smiod       sym_hashes = elf_sym_hashes (input_bfd);
384*3d8817e4Smiod 
385*3d8817e4Smiod       /* We'll need the symbol table in a second.  */
386*3d8817e4Smiod       symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
387*3d8817e4Smiod       if (symtab_hdr->sh_info == 0)
388*3d8817e4Smiod         continue;
389*3d8817e4Smiod 
390*3d8817e4Smiod       local_syms = all_local_syms[bfd_indx];
391*3d8817e4Smiod 
392*3d8817e4Smiod       /* Walk over each section attached to the input bfd.  */
393*3d8817e4Smiod       for (section = input_bfd->sections;
394*3d8817e4Smiod            section != NULL;
395*3d8817e4Smiod            section = section->next)
396*3d8817e4Smiod         {
397*3d8817e4Smiod           Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
398*3d8817e4Smiod 
399*3d8817e4Smiod           /* If there aren't any relocs, then there's nothing more
400*3d8817e4Smiod              to do.  */
401*3d8817e4Smiod           if ((section->flags & SEC_RELOC) == 0
402*3d8817e4Smiod               || section->reloc_count == 0)
403*3d8817e4Smiod             continue;
404*3d8817e4Smiod 
405*3d8817e4Smiod           /* If this section is a link-once section that will be
406*3d8817e4Smiod              discarded, then don't create any stubs.  */
407*3d8817e4Smiod           if (section->output_section == NULL
408*3d8817e4Smiod               || section->output_section->owner != output_bfd)
409*3d8817e4Smiod             continue;
410*3d8817e4Smiod 
411*3d8817e4Smiod           /* Get the relocs.  */
412*3d8817e4Smiod           internal_relocs
413*3d8817e4Smiod             = _bfd_elf_link_read_relocs (input_bfd, section, NULL,
414*3d8817e4Smiod 					 (Elf_Internal_Rela *) NULL,
415*3d8817e4Smiod 					 info->keep_memory);
416*3d8817e4Smiod           if (internal_relocs == NULL)
417*3d8817e4Smiod             goto error_ret_free_local;
418*3d8817e4Smiod 
419*3d8817e4Smiod           /* Now examine each relocation.  */
420*3d8817e4Smiod           irela = internal_relocs;
421*3d8817e4Smiod           irelaend = irela + section->reloc_count;
422*3d8817e4Smiod           for (; irela < irelaend; irela++)
423*3d8817e4Smiod             {
424*3d8817e4Smiod               unsigned int r_type, r_indx;
425*3d8817e4Smiod               struct elf32_m68hc11_stub_hash_entry *stub_entry;
426*3d8817e4Smiod               asection *sym_sec;
427*3d8817e4Smiod               bfd_vma sym_value;
428*3d8817e4Smiod               struct elf_link_hash_entry *hash;
429*3d8817e4Smiod               const char *stub_name;
430*3d8817e4Smiod               Elf_Internal_Sym *sym;
431*3d8817e4Smiod 
432*3d8817e4Smiod               r_type = ELF32_R_TYPE (irela->r_info);
433*3d8817e4Smiod 
434*3d8817e4Smiod               /* Only look at 16-bit relocs.  */
435*3d8817e4Smiod               if (r_type != (unsigned int) R_M68HC11_16)
436*3d8817e4Smiod                 continue;
437*3d8817e4Smiod 
438*3d8817e4Smiod               /* Now determine the call target, its name, value,
439*3d8817e4Smiod                  section.  */
440*3d8817e4Smiod               r_indx = ELF32_R_SYM (irela->r_info);
441*3d8817e4Smiod               if (r_indx < symtab_hdr->sh_info)
442*3d8817e4Smiod                 {
443*3d8817e4Smiod                   /* It's a local symbol.  */
444*3d8817e4Smiod                   Elf_Internal_Shdr *hdr;
445*3d8817e4Smiod                   bfd_boolean is_far;
446*3d8817e4Smiod 
447*3d8817e4Smiod                   sym = local_syms + r_indx;
448*3d8817e4Smiod                   is_far = (sym && (sym->st_other & STO_M68HC12_FAR));
449*3d8817e4Smiod                   if (!is_far)
450*3d8817e4Smiod                     continue;
451*3d8817e4Smiod 
452*3d8817e4Smiod                   hdr = elf_elfsections (input_bfd)[sym->st_shndx];
453*3d8817e4Smiod                   sym_sec = hdr->bfd_section;
454*3d8817e4Smiod                   stub_name = (bfd_elf_string_from_elf_section
455*3d8817e4Smiod                                (input_bfd, symtab_hdr->sh_link,
456*3d8817e4Smiod                                 sym->st_name));
457*3d8817e4Smiod                   sym_value = sym->st_value;
458*3d8817e4Smiod                   hash = NULL;
459*3d8817e4Smiod                 }
460*3d8817e4Smiod               else
461*3d8817e4Smiod                 {
462*3d8817e4Smiod                   /* It's an external symbol.  */
463*3d8817e4Smiod                   int e_indx;
464*3d8817e4Smiod 
465*3d8817e4Smiod                   e_indx = r_indx - symtab_hdr->sh_info;
466*3d8817e4Smiod                   hash = (struct elf_link_hash_entry *)
467*3d8817e4Smiod                     (sym_hashes[e_indx]);
468*3d8817e4Smiod 
469*3d8817e4Smiod                   while (hash->root.type == bfd_link_hash_indirect
470*3d8817e4Smiod                          || hash->root.type == bfd_link_hash_warning)
471*3d8817e4Smiod                     hash = ((struct elf_link_hash_entry *)
472*3d8817e4Smiod                             hash->root.u.i.link);
473*3d8817e4Smiod 
474*3d8817e4Smiod                   if (hash->root.type == bfd_link_hash_defined
475*3d8817e4Smiod                       || hash->root.type == bfd_link_hash_defweak
476*3d8817e4Smiod                       || hash->root.type == bfd_link_hash_new)
477*3d8817e4Smiod                     {
478*3d8817e4Smiod                       if (!(hash->other & STO_M68HC12_FAR))
479*3d8817e4Smiod                         continue;
480*3d8817e4Smiod                     }
481*3d8817e4Smiod                   else if (hash->root.type == bfd_link_hash_undefweak)
482*3d8817e4Smiod                     {
483*3d8817e4Smiod                       continue;
484*3d8817e4Smiod                     }
485*3d8817e4Smiod                   else if (hash->root.type == bfd_link_hash_undefined)
486*3d8817e4Smiod                     {
487*3d8817e4Smiod                       continue;
488*3d8817e4Smiod                     }
489*3d8817e4Smiod                   else
490*3d8817e4Smiod                     {
491*3d8817e4Smiod                       bfd_set_error (bfd_error_bad_value);
492*3d8817e4Smiod                       goto error_ret_free_internal;
493*3d8817e4Smiod                     }
494*3d8817e4Smiod                   sym_sec = hash->root.u.def.section;
495*3d8817e4Smiod                   sym_value = hash->root.u.def.value;
496*3d8817e4Smiod                   stub_name = hash->root.root.string;
497*3d8817e4Smiod                 }
498*3d8817e4Smiod 
499*3d8817e4Smiod               if (!stub_name)
500*3d8817e4Smiod                 goto error_ret_free_internal;
501*3d8817e4Smiod 
502*3d8817e4Smiod               stub_entry = m68hc12_stub_hash_lookup
503*3d8817e4Smiod                 (htab->stub_hash_table,
504*3d8817e4Smiod                  stub_name,
505*3d8817e4Smiod                  FALSE, FALSE);
506*3d8817e4Smiod               if (stub_entry == NULL)
507*3d8817e4Smiod                 {
508*3d8817e4Smiod                   if (add_stub_section == 0)
509*3d8817e4Smiod                     continue;
510*3d8817e4Smiod 
511*3d8817e4Smiod                   stub_entry = m68hc12_add_stub (stub_name, section, htab);
512*3d8817e4Smiod                   if (stub_entry == NULL)
513*3d8817e4Smiod                     {
514*3d8817e4Smiod                     error_ret_free_internal:
515*3d8817e4Smiod                       if (elf_section_data (section)->relocs == NULL)
516*3d8817e4Smiod                         free (internal_relocs);
517*3d8817e4Smiod                       goto error_ret_free_local;
518*3d8817e4Smiod                     }
519*3d8817e4Smiod                 }
520*3d8817e4Smiod 
521*3d8817e4Smiod               stub_entry->target_value = sym_value;
522*3d8817e4Smiod               stub_entry->target_section = sym_sec;
523*3d8817e4Smiod             }
524*3d8817e4Smiod 
525*3d8817e4Smiod           /* We're done with the internal relocs, free them.  */
526*3d8817e4Smiod           if (elf_section_data (section)->relocs == NULL)
527*3d8817e4Smiod             free (internal_relocs);
528*3d8817e4Smiod         }
529*3d8817e4Smiod     }
530*3d8817e4Smiod 
531*3d8817e4Smiod   if (add_stub_section)
532*3d8817e4Smiod     {
533*3d8817e4Smiod       /* OK, we've added some stubs.  Find out the new size of the
534*3d8817e4Smiod          stub sections.  */
535*3d8817e4Smiod       for (stub_sec = htab->stub_bfd->sections;
536*3d8817e4Smiod            stub_sec != NULL;
537*3d8817e4Smiod            stub_sec = stub_sec->next)
538*3d8817e4Smiod         {
539*3d8817e4Smiod           stub_sec->size = 0;
540*3d8817e4Smiod         }
541*3d8817e4Smiod 
542*3d8817e4Smiod       bfd_hash_traverse (htab->stub_hash_table, htab->size_one_stub, htab);
543*3d8817e4Smiod     }
544*3d8817e4Smiod   free (all_local_syms);
545*3d8817e4Smiod   return TRUE;
546*3d8817e4Smiod 
547*3d8817e4Smiod  error_ret_free_local:
548*3d8817e4Smiod   free (all_local_syms);
549*3d8817e4Smiod   return FALSE;
550*3d8817e4Smiod }
551*3d8817e4Smiod 
552*3d8817e4Smiod /* Export the trampoline addresses in the symbol table.  */
553*3d8817e4Smiod static bfd_boolean
m68hc11_elf_export_one_stub(struct bfd_hash_entry * gen_entry,void * in_arg)554*3d8817e4Smiod m68hc11_elf_export_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
555*3d8817e4Smiod {
556*3d8817e4Smiod   struct bfd_link_info *info;
557*3d8817e4Smiod   struct m68hc11_elf_link_hash_table *htab;
558*3d8817e4Smiod   struct elf32_m68hc11_stub_hash_entry *stub_entry;
559*3d8817e4Smiod   char* name;
560*3d8817e4Smiod   bfd_boolean result;
561*3d8817e4Smiod 
562*3d8817e4Smiod   info = (struct bfd_link_info *) in_arg;
563*3d8817e4Smiod   htab = m68hc11_elf_hash_table (info);
564*3d8817e4Smiod 
565*3d8817e4Smiod   /* Massage our args to the form they really have.  */
566*3d8817e4Smiod   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
567*3d8817e4Smiod 
568*3d8817e4Smiod   /* Generate the trampoline according to HC11 or HC12.  */
569*3d8817e4Smiod   result = (* htab->build_one_stub) (gen_entry, in_arg);
570*3d8817e4Smiod 
571*3d8817e4Smiod   /* Make a printable name that does not conflict with the real function.  */
572*3d8817e4Smiod   name = alloca (strlen (stub_entry->root.string) + 16);
573*3d8817e4Smiod   sprintf (name, "tramp.%s", stub_entry->root.string);
574*3d8817e4Smiod 
575*3d8817e4Smiod   /* Export the symbol for debugging/disassembling.  */
576*3d8817e4Smiod   m68hc11_elf_set_symbol (htab->stub_bfd, info, name,
577*3d8817e4Smiod                           stub_entry->stub_offset,
578*3d8817e4Smiod                           stub_entry->stub_sec);
579*3d8817e4Smiod   return result;
580*3d8817e4Smiod }
581*3d8817e4Smiod 
582*3d8817e4Smiod /* Export a symbol or set its value and section.  */
583*3d8817e4Smiod static void
m68hc11_elf_set_symbol(bfd * abfd,struct bfd_link_info * info,const char * name,bfd_vma value,asection * sec)584*3d8817e4Smiod m68hc11_elf_set_symbol (bfd *abfd, struct bfd_link_info *info,
585*3d8817e4Smiod                         const char *name, bfd_vma value, asection *sec)
586*3d8817e4Smiod {
587*3d8817e4Smiod   struct elf_link_hash_entry *h;
588*3d8817e4Smiod 
589*3d8817e4Smiod   h = (struct elf_link_hash_entry *)
590*3d8817e4Smiod     bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, FALSE);
591*3d8817e4Smiod   if (h == NULL)
592*3d8817e4Smiod     {
593*3d8817e4Smiod       _bfd_generic_link_add_one_symbol (info, abfd,
594*3d8817e4Smiod                                         name,
595*3d8817e4Smiod                                         BSF_GLOBAL,
596*3d8817e4Smiod                                         sec,
597*3d8817e4Smiod                                         value,
598*3d8817e4Smiod                                         (const char*) NULL,
599*3d8817e4Smiod                                         TRUE, FALSE, NULL);
600*3d8817e4Smiod     }
601*3d8817e4Smiod   else
602*3d8817e4Smiod     {
603*3d8817e4Smiod       h->root.type = bfd_link_hash_defined;
604*3d8817e4Smiod       h->root.u.def.value = value;
605*3d8817e4Smiod       h->root.u.def.section = sec;
606*3d8817e4Smiod     }
607*3d8817e4Smiod }
608*3d8817e4Smiod 
609*3d8817e4Smiod 
610*3d8817e4Smiod /* Build all the stubs associated with the current output file.  The
611*3d8817e4Smiod    stubs are kept in a hash table attached to the main linker hash
612*3d8817e4Smiod    table.  This function is called via m68hc12elf_finish in the
613*3d8817e4Smiod    linker.  */
614*3d8817e4Smiod 
615*3d8817e4Smiod bfd_boolean
elf32_m68hc11_build_stubs(bfd * abfd,struct bfd_link_info * info)616*3d8817e4Smiod elf32_m68hc11_build_stubs (bfd *abfd, struct bfd_link_info *info)
617*3d8817e4Smiod {
618*3d8817e4Smiod   asection *stub_sec;
619*3d8817e4Smiod   struct bfd_hash_table *table;
620*3d8817e4Smiod   struct m68hc11_elf_link_hash_table *htab;
621*3d8817e4Smiod   struct m68hc11_scan_param param;
622*3d8817e4Smiod 
623*3d8817e4Smiod   m68hc11_elf_get_bank_parameters (info);
624*3d8817e4Smiod   htab = m68hc11_elf_hash_table (info);
625*3d8817e4Smiod 
626*3d8817e4Smiod   for (stub_sec = htab->stub_bfd->sections;
627*3d8817e4Smiod        stub_sec != NULL;
628*3d8817e4Smiod        stub_sec = stub_sec->next)
629*3d8817e4Smiod     {
630*3d8817e4Smiod       bfd_size_type size;
631*3d8817e4Smiod 
632*3d8817e4Smiod       /* Allocate memory to hold the linker stubs.  */
633*3d8817e4Smiod       size = stub_sec->size;
634*3d8817e4Smiod       stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, size);
635*3d8817e4Smiod       if (stub_sec->contents == NULL && size != 0)
636*3d8817e4Smiod 	return FALSE;
637*3d8817e4Smiod       stub_sec->size = 0;
638*3d8817e4Smiod     }
639*3d8817e4Smiod 
640*3d8817e4Smiod   /* Build the stubs as directed by the stub hash table.  */
641*3d8817e4Smiod   table = htab->stub_hash_table;
642*3d8817e4Smiod   bfd_hash_traverse (table, m68hc11_elf_export_one_stub, info);
643*3d8817e4Smiod 
644*3d8817e4Smiod   /* Scan the output sections to see if we use the memory banks.
645*3d8817e4Smiod      If so, export the symbols that define how the memory banks
646*3d8817e4Smiod      are mapped.  This is used by gdb and the simulator to obtain
647*3d8817e4Smiod      the information.  It can be used by programs to burn the eprom
648*3d8817e4Smiod      at the good addresses.  */
649*3d8817e4Smiod   param.use_memory_banks = FALSE;
650*3d8817e4Smiod   param.pinfo = &htab->pinfo;
651*3d8817e4Smiod   bfd_map_over_sections (abfd, scan_sections_for_abi, &param);
652*3d8817e4Smiod   if (param.use_memory_banks)
653*3d8817e4Smiod     {
654*3d8817e4Smiod       m68hc11_elf_set_symbol (abfd, info, BFD_M68HC11_BANK_START_NAME,
655*3d8817e4Smiod                               htab->pinfo.bank_physical,
656*3d8817e4Smiod                               bfd_abs_section_ptr);
657*3d8817e4Smiod       m68hc11_elf_set_symbol (abfd, info, BFD_M68HC11_BANK_VIRTUAL_NAME,
658*3d8817e4Smiod                               htab->pinfo.bank_virtual,
659*3d8817e4Smiod                               bfd_abs_section_ptr);
660*3d8817e4Smiod       m68hc11_elf_set_symbol (abfd, info, BFD_M68HC11_BANK_SIZE_NAME,
661*3d8817e4Smiod                               htab->pinfo.bank_size,
662*3d8817e4Smiod                               bfd_abs_section_ptr);
663*3d8817e4Smiod     }
664*3d8817e4Smiod 
665*3d8817e4Smiod   return TRUE;
666*3d8817e4Smiod }
667*3d8817e4Smiod 
668*3d8817e4Smiod void
m68hc11_elf_get_bank_parameters(struct bfd_link_info * info)669*3d8817e4Smiod m68hc11_elf_get_bank_parameters (struct bfd_link_info *info)
670*3d8817e4Smiod {
671*3d8817e4Smiod   unsigned i;
672*3d8817e4Smiod   struct m68hc11_page_info *pinfo;
673*3d8817e4Smiod   struct bfd_link_hash_entry *h;
674*3d8817e4Smiod 
675*3d8817e4Smiod   pinfo = &m68hc11_elf_hash_table (info)->pinfo;
676*3d8817e4Smiod   if (pinfo->bank_param_initialized)
677*3d8817e4Smiod     return;
678*3d8817e4Smiod 
679*3d8817e4Smiod   pinfo->bank_virtual = M68HC12_BANK_VIRT;
680*3d8817e4Smiod   pinfo->bank_mask = M68HC12_BANK_MASK;
681*3d8817e4Smiod   pinfo->bank_physical = M68HC12_BANK_BASE;
682*3d8817e4Smiod   pinfo->bank_shift = M68HC12_BANK_SHIFT;
683*3d8817e4Smiod   pinfo->bank_size = 1 << M68HC12_BANK_SHIFT;
684*3d8817e4Smiod 
685*3d8817e4Smiod   h = bfd_link_hash_lookup (info->hash, BFD_M68HC11_BANK_START_NAME,
686*3d8817e4Smiod                             FALSE, FALSE, TRUE);
687*3d8817e4Smiod   if (h != (struct bfd_link_hash_entry*) NULL
688*3d8817e4Smiod       && h->type == bfd_link_hash_defined)
689*3d8817e4Smiod     pinfo->bank_physical = (h->u.def.value
690*3d8817e4Smiod                             + h->u.def.section->output_section->vma
691*3d8817e4Smiod                             + h->u.def.section->output_offset);
692*3d8817e4Smiod 
693*3d8817e4Smiod   h = bfd_link_hash_lookup (info->hash, BFD_M68HC11_BANK_VIRTUAL_NAME,
694*3d8817e4Smiod                             FALSE, FALSE, TRUE);
695*3d8817e4Smiod   if (h != (struct bfd_link_hash_entry*) NULL
696*3d8817e4Smiod       && h->type == bfd_link_hash_defined)
697*3d8817e4Smiod     pinfo->bank_virtual = (h->u.def.value
698*3d8817e4Smiod                            + h->u.def.section->output_section->vma
699*3d8817e4Smiod                            + h->u.def.section->output_offset);
700*3d8817e4Smiod 
701*3d8817e4Smiod   h = bfd_link_hash_lookup (info->hash, BFD_M68HC11_BANK_SIZE_NAME,
702*3d8817e4Smiod                             FALSE, FALSE, TRUE);
703*3d8817e4Smiod   if (h != (struct bfd_link_hash_entry*) NULL
704*3d8817e4Smiod       && h->type == bfd_link_hash_defined)
705*3d8817e4Smiod     pinfo->bank_size = (h->u.def.value
706*3d8817e4Smiod                         + h->u.def.section->output_section->vma
707*3d8817e4Smiod                         + h->u.def.section->output_offset);
708*3d8817e4Smiod 
709*3d8817e4Smiod   pinfo->bank_shift = 0;
710*3d8817e4Smiod   for (i = pinfo->bank_size; i != 0; i >>= 1)
711*3d8817e4Smiod     pinfo->bank_shift++;
712*3d8817e4Smiod   pinfo->bank_shift--;
713*3d8817e4Smiod   pinfo->bank_mask = (1 << pinfo->bank_shift) - 1;
714*3d8817e4Smiod   pinfo->bank_physical_end = pinfo->bank_physical + pinfo->bank_size;
715*3d8817e4Smiod   pinfo->bank_param_initialized = 1;
716*3d8817e4Smiod 
717*3d8817e4Smiod   h = bfd_link_hash_lookup (info->hash, "__far_trampoline", FALSE,
718*3d8817e4Smiod                             FALSE, TRUE);
719*3d8817e4Smiod   if (h != (struct bfd_link_hash_entry*) NULL
720*3d8817e4Smiod       && h->type == bfd_link_hash_defined)
721*3d8817e4Smiod     pinfo->trampoline_addr = (h->u.def.value
722*3d8817e4Smiod                               + h->u.def.section->output_section->vma
723*3d8817e4Smiod                               + h->u.def.section->output_offset);
724*3d8817e4Smiod }
725*3d8817e4Smiod 
726*3d8817e4Smiod /* Return 1 if the address is in banked memory.
727*3d8817e4Smiod    This can be applied to a virtual address and to a physical address.  */
728*3d8817e4Smiod int
m68hc11_addr_is_banked(struct m68hc11_page_info * pinfo,bfd_vma addr)729*3d8817e4Smiod m68hc11_addr_is_banked (struct m68hc11_page_info *pinfo, bfd_vma addr)
730*3d8817e4Smiod {
731*3d8817e4Smiod   if (addr >= pinfo->bank_virtual)
732*3d8817e4Smiod     return 1;
733*3d8817e4Smiod 
734*3d8817e4Smiod   if (addr >= pinfo->bank_physical && addr <= pinfo->bank_physical_end)
735*3d8817e4Smiod     return 1;
736*3d8817e4Smiod 
737*3d8817e4Smiod   return 0;
738*3d8817e4Smiod }
739*3d8817e4Smiod 
740*3d8817e4Smiod /* Return the physical address seen by the processor, taking
741*3d8817e4Smiod    into account banked memory.  */
742*3d8817e4Smiod bfd_vma
m68hc11_phys_addr(struct m68hc11_page_info * pinfo,bfd_vma addr)743*3d8817e4Smiod m68hc11_phys_addr (struct m68hc11_page_info *pinfo, bfd_vma addr)
744*3d8817e4Smiod {
745*3d8817e4Smiod   if (addr < pinfo->bank_virtual)
746*3d8817e4Smiod     return addr;
747*3d8817e4Smiod 
748*3d8817e4Smiod   /* Map the address to the memory bank.  */
749*3d8817e4Smiod   addr -= pinfo->bank_virtual;
750*3d8817e4Smiod   addr &= pinfo->bank_mask;
751*3d8817e4Smiod   addr += pinfo->bank_physical;
752*3d8817e4Smiod   return addr;
753*3d8817e4Smiod }
754*3d8817e4Smiod 
755*3d8817e4Smiod /* Return the page number corresponding to an address in banked memory.  */
756*3d8817e4Smiod bfd_vma
m68hc11_phys_page(struct m68hc11_page_info * pinfo,bfd_vma addr)757*3d8817e4Smiod m68hc11_phys_page (struct m68hc11_page_info *pinfo, bfd_vma addr)
758*3d8817e4Smiod {
759*3d8817e4Smiod   if (addr < pinfo->bank_virtual)
760*3d8817e4Smiod     return 0;
761*3d8817e4Smiod 
762*3d8817e4Smiod   /* Map the address to the memory bank.  */
763*3d8817e4Smiod   addr -= pinfo->bank_virtual;
764*3d8817e4Smiod   addr >>= pinfo->bank_shift;
765*3d8817e4Smiod   addr &= 0x0ff;
766*3d8817e4Smiod   return addr;
767*3d8817e4Smiod }
768*3d8817e4Smiod 
769*3d8817e4Smiod /* This function is used for relocs which are only used for relaxing,
770*3d8817e4Smiod    which the linker should otherwise ignore.  */
771*3d8817e4Smiod 
772*3d8817e4Smiod bfd_reloc_status_type
m68hc11_elf_ignore_reloc(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry,asymbol * symbol ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)773*3d8817e4Smiod m68hc11_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
774*3d8817e4Smiod                           arelent *reloc_entry,
775*3d8817e4Smiod                           asymbol *symbol ATTRIBUTE_UNUSED,
776*3d8817e4Smiod                           void *data ATTRIBUTE_UNUSED,
777*3d8817e4Smiod                           asection *input_section,
778*3d8817e4Smiod                           bfd *output_bfd,
779*3d8817e4Smiod                           char **error_message ATTRIBUTE_UNUSED)
780*3d8817e4Smiod {
781*3d8817e4Smiod   if (output_bfd != NULL)
782*3d8817e4Smiod     reloc_entry->address += input_section->output_offset;
783*3d8817e4Smiod   return bfd_reloc_ok;
784*3d8817e4Smiod }
785*3d8817e4Smiod 
786*3d8817e4Smiod bfd_reloc_status_type
m68hc11_elf_special_reloc(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry,asymbol * symbol,void * data ATTRIBUTE_UNUSED,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)787*3d8817e4Smiod m68hc11_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
788*3d8817e4Smiod                            arelent *reloc_entry,
789*3d8817e4Smiod                            asymbol *symbol,
790*3d8817e4Smiod                            void *data ATTRIBUTE_UNUSED,
791*3d8817e4Smiod                            asection *input_section,
792*3d8817e4Smiod                            bfd *output_bfd,
793*3d8817e4Smiod                            char **error_message ATTRIBUTE_UNUSED)
794*3d8817e4Smiod {
795*3d8817e4Smiod   if (output_bfd != (bfd *) NULL
796*3d8817e4Smiod       && (symbol->flags & BSF_SECTION_SYM) == 0
797*3d8817e4Smiod       && (! reloc_entry->howto->partial_inplace
798*3d8817e4Smiod 	  || reloc_entry->addend == 0))
799*3d8817e4Smiod     {
800*3d8817e4Smiod       reloc_entry->address += input_section->output_offset;
801*3d8817e4Smiod       return bfd_reloc_ok;
802*3d8817e4Smiod     }
803*3d8817e4Smiod 
804*3d8817e4Smiod   if (output_bfd != NULL)
805*3d8817e4Smiod     return bfd_reloc_continue;
806*3d8817e4Smiod 
807*3d8817e4Smiod   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
808*3d8817e4Smiod     return bfd_reloc_outofrange;
809*3d8817e4Smiod 
810*3d8817e4Smiod   abort();
811*3d8817e4Smiod }
812*3d8817e4Smiod 
813*3d8817e4Smiod asection *
elf32_m68hc11_gc_mark_hook(asection * sec,struct bfd_link_info * info ATTRIBUTE_UNUSED,Elf_Internal_Rela * rel,struct elf_link_hash_entry * h,Elf_Internal_Sym * sym)814*3d8817e4Smiod elf32_m68hc11_gc_mark_hook (asection *sec,
815*3d8817e4Smiod                             struct bfd_link_info *info ATTRIBUTE_UNUSED,
816*3d8817e4Smiod                             Elf_Internal_Rela *rel,
817*3d8817e4Smiod                             struct elf_link_hash_entry *h,
818*3d8817e4Smiod                             Elf_Internal_Sym *sym)
819*3d8817e4Smiod {
820*3d8817e4Smiod   if (h != NULL)
821*3d8817e4Smiod     {
822*3d8817e4Smiod       switch (ELF32_R_TYPE (rel->r_info))
823*3d8817e4Smiod 	{
824*3d8817e4Smiod 	default:
825*3d8817e4Smiod 	  switch (h->root.type)
826*3d8817e4Smiod 	    {
827*3d8817e4Smiod 	    case bfd_link_hash_defined:
828*3d8817e4Smiod 	    case bfd_link_hash_defweak:
829*3d8817e4Smiod 	      return h->root.u.def.section;
830*3d8817e4Smiod 
831*3d8817e4Smiod 	    case bfd_link_hash_common:
832*3d8817e4Smiod 	      return h->root.u.c.p->section;
833*3d8817e4Smiod 
834*3d8817e4Smiod 	    default:
835*3d8817e4Smiod 	      break;
836*3d8817e4Smiod 	    }
837*3d8817e4Smiod 	}
838*3d8817e4Smiod     }
839*3d8817e4Smiod   else
840*3d8817e4Smiod     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
841*3d8817e4Smiod 
842*3d8817e4Smiod   return NULL;
843*3d8817e4Smiod }
844*3d8817e4Smiod 
845*3d8817e4Smiod bfd_boolean
elf32_m68hc11_gc_sweep_hook(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * sec ATTRIBUTE_UNUSED,const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)846*3d8817e4Smiod elf32_m68hc11_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
847*3d8817e4Smiod                              struct bfd_link_info *info ATTRIBUTE_UNUSED,
848*3d8817e4Smiod                              asection *sec ATTRIBUTE_UNUSED,
849*3d8817e4Smiod                              const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
850*3d8817e4Smiod {
851*3d8817e4Smiod   /* We don't use got and plt entries for 68hc11/68hc12.  */
852*3d8817e4Smiod   return TRUE;
853*3d8817e4Smiod }
854*3d8817e4Smiod 
855*3d8817e4Smiod /* Look through the relocs for a section during the first phase.
856*3d8817e4Smiod    Since we don't do .gots or .plts, we just need to consider the
857*3d8817e4Smiod    virtual table relocs for gc.  */
858*3d8817e4Smiod 
859*3d8817e4Smiod bfd_boolean
elf32_m68hc11_check_relocs(bfd * abfd,struct bfd_link_info * info,asection * sec,const Elf_Internal_Rela * relocs)860*3d8817e4Smiod elf32_m68hc11_check_relocs (bfd *abfd, struct bfd_link_info *info,
861*3d8817e4Smiod                             asection *sec, const Elf_Internal_Rela *relocs)
862*3d8817e4Smiod {
863*3d8817e4Smiod   Elf_Internal_Shdr *           symtab_hdr;
864*3d8817e4Smiod   struct elf_link_hash_entry ** sym_hashes;
865*3d8817e4Smiod   struct elf_link_hash_entry ** sym_hashes_end;
866*3d8817e4Smiod   const Elf_Internal_Rela *     rel;
867*3d8817e4Smiod   const Elf_Internal_Rela *     rel_end;
868*3d8817e4Smiod 
869*3d8817e4Smiod   if (info->relocatable)
870*3d8817e4Smiod     return TRUE;
871*3d8817e4Smiod 
872*3d8817e4Smiod   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
873*3d8817e4Smiod   sym_hashes = elf_sym_hashes (abfd);
874*3d8817e4Smiod   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
875*3d8817e4Smiod   if (!elf_bad_symtab (abfd))
876*3d8817e4Smiod     sym_hashes_end -= symtab_hdr->sh_info;
877*3d8817e4Smiod 
878*3d8817e4Smiod   rel_end = relocs + sec->reloc_count;
879*3d8817e4Smiod 
880*3d8817e4Smiod   for (rel = relocs; rel < rel_end; rel++)
881*3d8817e4Smiod     {
882*3d8817e4Smiod       struct elf_link_hash_entry * h;
883*3d8817e4Smiod       unsigned long r_symndx;
884*3d8817e4Smiod 
885*3d8817e4Smiod       r_symndx = ELF32_R_SYM (rel->r_info);
886*3d8817e4Smiod 
887*3d8817e4Smiod       if (r_symndx < symtab_hdr->sh_info)
888*3d8817e4Smiod         h = NULL;
889*3d8817e4Smiod       else
890*3d8817e4Smiod 	{
891*3d8817e4Smiod 	  h = sym_hashes [r_symndx - symtab_hdr->sh_info];
892*3d8817e4Smiod 	  while (h->root.type == bfd_link_hash_indirect
893*3d8817e4Smiod 		 || h->root.type == bfd_link_hash_warning)
894*3d8817e4Smiod 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
895*3d8817e4Smiod 	}
896*3d8817e4Smiod 
897*3d8817e4Smiod       switch (ELF32_R_TYPE (rel->r_info))
898*3d8817e4Smiod         {
899*3d8817e4Smiod         /* This relocation describes the C++ object vtable hierarchy.
900*3d8817e4Smiod            Reconstruct it for later use during GC.  */
901*3d8817e4Smiod         case R_M68HC11_GNU_VTINHERIT:
902*3d8817e4Smiod           if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
903*3d8817e4Smiod             return FALSE;
904*3d8817e4Smiod           break;
905*3d8817e4Smiod 
906*3d8817e4Smiod         /* This relocation describes which C++ vtable entries are actually
907*3d8817e4Smiod            used.  Record for later use during GC.  */
908*3d8817e4Smiod         case R_M68HC11_GNU_VTENTRY:
909*3d8817e4Smiod           if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
910*3d8817e4Smiod             return FALSE;
911*3d8817e4Smiod           break;
912*3d8817e4Smiod         }
913*3d8817e4Smiod     }
914*3d8817e4Smiod 
915*3d8817e4Smiod   return TRUE;
916*3d8817e4Smiod }
917*3d8817e4Smiod 
918*3d8817e4Smiod static bfd_boolean
m68hc11_get_relocation_value(bfd * input_bfd,struct bfd_link_info * info,asection * input_section,asection ** local_sections,Elf_Internal_Sym * local_syms,Elf_Internal_Rela * rel,const char ** name,bfd_vma * relocation,bfd_boolean * is_far)919*3d8817e4Smiod m68hc11_get_relocation_value (bfd *input_bfd, struct bfd_link_info *info,
920*3d8817e4Smiod 			      asection *input_section,
921*3d8817e4Smiod                               asection **local_sections,
922*3d8817e4Smiod                               Elf_Internal_Sym *local_syms,
923*3d8817e4Smiod                               Elf_Internal_Rela *rel,
924*3d8817e4Smiod                               const char **name,
925*3d8817e4Smiod                               bfd_vma *relocation, bfd_boolean *is_far)
926*3d8817e4Smiod {
927*3d8817e4Smiod   Elf_Internal_Shdr *symtab_hdr;
928*3d8817e4Smiod   struct elf_link_hash_entry **sym_hashes;
929*3d8817e4Smiod   unsigned long r_symndx;
930*3d8817e4Smiod   asection *sec;
931*3d8817e4Smiod   struct elf_link_hash_entry *h;
932*3d8817e4Smiod   Elf_Internal_Sym *sym;
933*3d8817e4Smiod   const char* stub_name = 0;
934*3d8817e4Smiod 
935*3d8817e4Smiod   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
936*3d8817e4Smiod   sym_hashes = elf_sym_hashes (input_bfd);
937*3d8817e4Smiod 
938*3d8817e4Smiod   r_symndx = ELF32_R_SYM (rel->r_info);
939*3d8817e4Smiod 
940*3d8817e4Smiod   /* This is a final link.  */
941*3d8817e4Smiod   h = NULL;
942*3d8817e4Smiod   sym = NULL;
943*3d8817e4Smiod   sec = NULL;
944*3d8817e4Smiod   if (r_symndx < symtab_hdr->sh_info)
945*3d8817e4Smiod     {
946*3d8817e4Smiod       sym = local_syms + r_symndx;
947*3d8817e4Smiod       sec = local_sections[r_symndx];
948*3d8817e4Smiod       *relocation = (sec->output_section->vma
949*3d8817e4Smiod                      + sec->output_offset
950*3d8817e4Smiod                      + sym->st_value);
951*3d8817e4Smiod       *is_far = (sym && (sym->st_other & STO_M68HC12_FAR));
952*3d8817e4Smiod       if (*is_far)
953*3d8817e4Smiod         stub_name = (bfd_elf_string_from_elf_section
954*3d8817e4Smiod                      (input_bfd, symtab_hdr->sh_link,
955*3d8817e4Smiod                       sym->st_name));
956*3d8817e4Smiod     }
957*3d8817e4Smiod   else
958*3d8817e4Smiod     {
959*3d8817e4Smiod       bfd_boolean unresolved_reloc, warned;
960*3d8817e4Smiod 
961*3d8817e4Smiod       RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
962*3d8817e4Smiod 			       r_symndx, symtab_hdr, sym_hashes,
963*3d8817e4Smiod 			       h, sec, *relocation, unresolved_reloc, warned);
964*3d8817e4Smiod 
965*3d8817e4Smiod       *is_far = (h && (h->other & STO_M68HC12_FAR));
966*3d8817e4Smiod       stub_name = h->root.root.string;
967*3d8817e4Smiod     }
968*3d8817e4Smiod 
969*3d8817e4Smiod   if (h != NULL)
970*3d8817e4Smiod     *name = h->root.root.string;
971*3d8817e4Smiod   else
972*3d8817e4Smiod     {
973*3d8817e4Smiod       *name = (bfd_elf_string_from_elf_section
974*3d8817e4Smiod                (input_bfd, symtab_hdr->sh_link, sym->st_name));
975*3d8817e4Smiod       if (*name == NULL || **name == '\0')
976*3d8817e4Smiod         *name = bfd_section_name (input_bfd, sec);
977*3d8817e4Smiod     }
978*3d8817e4Smiod 
979*3d8817e4Smiod   if (*is_far && ELF32_R_TYPE (rel->r_info) == R_M68HC11_16)
980*3d8817e4Smiod     {
981*3d8817e4Smiod       struct elf32_m68hc11_stub_hash_entry* stub;
982*3d8817e4Smiod       struct m68hc11_elf_link_hash_table *htab;
983*3d8817e4Smiod 
984*3d8817e4Smiod       htab = m68hc11_elf_hash_table (info);
985*3d8817e4Smiod       stub = m68hc12_stub_hash_lookup (htab->stub_hash_table,
986*3d8817e4Smiod                                        *name, FALSE, FALSE);
987*3d8817e4Smiod       if (stub)
988*3d8817e4Smiod         {
989*3d8817e4Smiod           *relocation = stub->stub_offset
990*3d8817e4Smiod             + stub->stub_sec->output_section->vma
991*3d8817e4Smiod             + stub->stub_sec->output_offset;
992*3d8817e4Smiod           *is_far = FALSE;
993*3d8817e4Smiod         }
994*3d8817e4Smiod     }
995*3d8817e4Smiod   return TRUE;
996*3d8817e4Smiod }
997*3d8817e4Smiod 
998*3d8817e4Smiod /* Relocate a 68hc11/68hc12 ELF section.  */
999*3d8817e4Smiod bfd_boolean
elf32_m68hc11_relocate_section(bfd * output_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,Elf_Internal_Rela * relocs,Elf_Internal_Sym * local_syms,asection ** local_sections)1000*3d8817e4Smiod elf32_m68hc11_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
1001*3d8817e4Smiod                                 struct bfd_link_info *info,
1002*3d8817e4Smiod                                 bfd *input_bfd, asection *input_section,
1003*3d8817e4Smiod                                 bfd_byte *contents, Elf_Internal_Rela *relocs,
1004*3d8817e4Smiod                                 Elf_Internal_Sym *local_syms,
1005*3d8817e4Smiod                                 asection **local_sections)
1006*3d8817e4Smiod {
1007*3d8817e4Smiod   Elf_Internal_Shdr *symtab_hdr;
1008*3d8817e4Smiod   struct elf_link_hash_entry **sym_hashes;
1009*3d8817e4Smiod   Elf_Internal_Rela *rel, *relend;
1010*3d8817e4Smiod   const char *name = NULL;
1011*3d8817e4Smiod   struct m68hc11_page_info *pinfo;
1012*3d8817e4Smiod   const struct elf_backend_data * const ebd = get_elf_backend_data (input_bfd);
1013*3d8817e4Smiod 
1014*3d8817e4Smiod   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1015*3d8817e4Smiod   sym_hashes = elf_sym_hashes (input_bfd);
1016*3d8817e4Smiod 
1017*3d8817e4Smiod   /* Get memory bank parameters.  */
1018*3d8817e4Smiod   m68hc11_elf_get_bank_parameters (info);
1019*3d8817e4Smiod   pinfo = &m68hc11_elf_hash_table (info)->pinfo;
1020*3d8817e4Smiod 
1021*3d8817e4Smiod   rel = relocs;
1022*3d8817e4Smiod   relend = relocs + input_section->reloc_count;
1023*3d8817e4Smiod   for (; rel < relend; rel++)
1024*3d8817e4Smiod     {
1025*3d8817e4Smiod       int r_type;
1026*3d8817e4Smiod       arelent arel;
1027*3d8817e4Smiod       reloc_howto_type *howto;
1028*3d8817e4Smiod       unsigned long r_symndx;
1029*3d8817e4Smiod       Elf_Internal_Sym *sym;
1030*3d8817e4Smiod       asection *sec;
1031*3d8817e4Smiod       bfd_vma relocation = 0;
1032*3d8817e4Smiod       bfd_reloc_status_type r = bfd_reloc_undefined;
1033*3d8817e4Smiod       bfd_vma phys_page;
1034*3d8817e4Smiod       bfd_vma phys_addr;
1035*3d8817e4Smiod       bfd_vma insn_addr;
1036*3d8817e4Smiod       bfd_vma insn_page;
1037*3d8817e4Smiod       bfd_boolean is_far = FALSE;
1038*3d8817e4Smiod 
1039*3d8817e4Smiod       r_symndx = ELF32_R_SYM (rel->r_info);
1040*3d8817e4Smiod       r_type = ELF32_R_TYPE (rel->r_info);
1041*3d8817e4Smiod 
1042*3d8817e4Smiod       if (r_type == R_M68HC11_GNU_VTENTRY
1043*3d8817e4Smiod           || r_type == R_M68HC11_GNU_VTINHERIT )
1044*3d8817e4Smiod         continue;
1045*3d8817e4Smiod 
1046*3d8817e4Smiod       if (info->relocatable)
1047*3d8817e4Smiod 	{
1048*3d8817e4Smiod 	  /* This is a relocatable link.  We don't have to change
1049*3d8817e4Smiod 	     anything, unless the reloc is against a section symbol,
1050*3d8817e4Smiod 	     in which case we have to adjust according to where the
1051*3d8817e4Smiod 	     section symbol winds up in the output section.  */
1052*3d8817e4Smiod 	  if (r_symndx < symtab_hdr->sh_info)
1053*3d8817e4Smiod 	    {
1054*3d8817e4Smiod 	      sym = local_syms + r_symndx;
1055*3d8817e4Smiod 	      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1056*3d8817e4Smiod 		{
1057*3d8817e4Smiod 		  sec = local_sections[r_symndx];
1058*3d8817e4Smiod 		  rel->r_addend += sec->output_offset + sym->st_value;
1059*3d8817e4Smiod 		}
1060*3d8817e4Smiod 	    }
1061*3d8817e4Smiod 
1062*3d8817e4Smiod 	  continue;
1063*3d8817e4Smiod 	}
1064*3d8817e4Smiod       (*ebd->elf_info_to_howto_rel) (input_bfd, &arel, rel);
1065*3d8817e4Smiod       howto = arel.howto;
1066*3d8817e4Smiod 
1067*3d8817e4Smiod       m68hc11_get_relocation_value (input_bfd, info, input_section,
1068*3d8817e4Smiod 				    local_sections, local_syms,
1069*3d8817e4Smiod                                     rel, &name, &relocation, &is_far);
1070*3d8817e4Smiod 
1071*3d8817e4Smiod       /* Do the memory bank mapping.  */
1072*3d8817e4Smiod       phys_addr = m68hc11_phys_addr (pinfo, relocation + rel->r_addend);
1073*3d8817e4Smiod       phys_page = m68hc11_phys_page (pinfo, relocation + rel->r_addend);
1074*3d8817e4Smiod       switch (r_type)
1075*3d8817e4Smiod         {
1076*3d8817e4Smiod         case R_M68HC11_24:
1077*3d8817e4Smiod           /* Reloc used by 68HC12 call instruction.  */
1078*3d8817e4Smiod           bfd_put_16 (input_bfd, phys_addr,
1079*3d8817e4Smiod                       (bfd_byte*) contents + rel->r_offset);
1080*3d8817e4Smiod           bfd_put_8 (input_bfd, phys_page,
1081*3d8817e4Smiod                      (bfd_byte*) contents + rel->r_offset + 2);
1082*3d8817e4Smiod           r = bfd_reloc_ok;
1083*3d8817e4Smiod           r_type = R_M68HC11_NONE;
1084*3d8817e4Smiod           break;
1085*3d8817e4Smiod 
1086*3d8817e4Smiod         case R_M68HC11_NONE:
1087*3d8817e4Smiod           r = bfd_reloc_ok;
1088*3d8817e4Smiod           break;
1089*3d8817e4Smiod 
1090*3d8817e4Smiod         case R_M68HC11_LO16:
1091*3d8817e4Smiod           /* Reloc generated by %addr(expr) gas to obtain the
1092*3d8817e4Smiod              address as mapped in the memory bank window.  */
1093*3d8817e4Smiod           relocation = phys_addr;
1094*3d8817e4Smiod           break;
1095*3d8817e4Smiod 
1096*3d8817e4Smiod         case R_M68HC11_PAGE:
1097*3d8817e4Smiod           /* Reloc generated by %page(expr) gas to obtain the
1098*3d8817e4Smiod              page number associated with the address.  */
1099*3d8817e4Smiod           relocation = phys_page;
1100*3d8817e4Smiod           break;
1101*3d8817e4Smiod 
1102*3d8817e4Smiod         case R_M68HC11_16:
1103*3d8817e4Smiod           /* Get virtual address of instruction having the relocation.  */
1104*3d8817e4Smiod           if (is_far)
1105*3d8817e4Smiod             {
1106*3d8817e4Smiod               const char* msg;
1107*3d8817e4Smiod               char* buf;
1108*3d8817e4Smiod               msg = _("Reference to the far symbol `%s' using a wrong "
1109*3d8817e4Smiod                       "relocation may result in incorrect execution");
1110*3d8817e4Smiod               buf = alloca (strlen (msg) + strlen (name) + 10);
1111*3d8817e4Smiod               sprintf (buf, msg, name);
1112*3d8817e4Smiod 
1113*3d8817e4Smiod               (* info->callbacks->warning)
1114*3d8817e4Smiod                 (info, buf, name, input_bfd, NULL, rel->r_offset);
1115*3d8817e4Smiod             }
1116*3d8817e4Smiod 
1117*3d8817e4Smiod           /* Get virtual address of instruction having the relocation.  */
1118*3d8817e4Smiod           insn_addr = input_section->output_section->vma
1119*3d8817e4Smiod             + input_section->output_offset
1120*3d8817e4Smiod             + rel->r_offset;
1121*3d8817e4Smiod 
1122*3d8817e4Smiod           insn_page = m68hc11_phys_page (pinfo, insn_addr);
1123*3d8817e4Smiod 
1124*3d8817e4Smiod           if (m68hc11_addr_is_banked (pinfo, relocation + rel->r_addend)
1125*3d8817e4Smiod               && m68hc11_addr_is_banked (pinfo, insn_addr)
1126*3d8817e4Smiod               && phys_page != insn_page)
1127*3d8817e4Smiod             {
1128*3d8817e4Smiod               const char* msg;
1129*3d8817e4Smiod               char* buf;
1130*3d8817e4Smiod 
1131*3d8817e4Smiod               msg = _("banked address [%lx:%04lx] (%lx) is not in the same bank "
1132*3d8817e4Smiod                       "as current banked address [%lx:%04lx] (%lx)");
1133*3d8817e4Smiod 
1134*3d8817e4Smiod               buf = alloca (strlen (msg) + 128);
1135*3d8817e4Smiod               sprintf (buf, msg, phys_page, phys_addr,
1136*3d8817e4Smiod                        (long) (relocation + rel->r_addend),
1137*3d8817e4Smiod                        insn_page, m68hc11_phys_addr (pinfo, insn_addr),
1138*3d8817e4Smiod                        (long) (insn_addr));
1139*3d8817e4Smiod               if (!((*info->callbacks->warning)
1140*3d8817e4Smiod                     (info, buf, name, input_bfd, input_section,
1141*3d8817e4Smiod                      rel->r_offset)))
1142*3d8817e4Smiod                 return FALSE;
1143*3d8817e4Smiod               break;
1144*3d8817e4Smiod             }
1145*3d8817e4Smiod           if (phys_page != 0 && insn_page == 0)
1146*3d8817e4Smiod             {
1147*3d8817e4Smiod               const char* msg;
1148*3d8817e4Smiod               char* buf;
1149*3d8817e4Smiod 
1150*3d8817e4Smiod               msg = _("reference to a banked address [%lx:%04lx] in the "
1151*3d8817e4Smiod                       "normal address space at %04lx");
1152*3d8817e4Smiod 
1153*3d8817e4Smiod               buf = alloca (strlen (msg) + 128);
1154*3d8817e4Smiod               sprintf (buf, msg, phys_page, phys_addr, insn_addr);
1155*3d8817e4Smiod               if (!((*info->callbacks->warning)
1156*3d8817e4Smiod                     (info, buf, name, input_bfd, input_section,
1157*3d8817e4Smiod                      insn_addr)))
1158*3d8817e4Smiod                 return FALSE;
1159*3d8817e4Smiod 
1160*3d8817e4Smiod               relocation = phys_addr;
1161*3d8817e4Smiod               break;
1162*3d8817e4Smiod             }
1163*3d8817e4Smiod 
1164*3d8817e4Smiod           /* If this is a banked address use the phys_addr so that
1165*3d8817e4Smiod              we stay in the banked window.  */
1166*3d8817e4Smiod           if (m68hc11_addr_is_banked (pinfo, relocation + rel->r_addend))
1167*3d8817e4Smiod             relocation = phys_addr;
1168*3d8817e4Smiod           break;
1169*3d8817e4Smiod         }
1170*3d8817e4Smiod       if (r_type != R_M68HC11_NONE)
1171*3d8817e4Smiod         r = _bfd_final_link_relocate (howto, input_bfd, input_section,
1172*3d8817e4Smiod                                       contents, rel->r_offset,
1173*3d8817e4Smiod                                       relocation, rel->r_addend);
1174*3d8817e4Smiod 
1175*3d8817e4Smiod       if (r != bfd_reloc_ok)
1176*3d8817e4Smiod 	{
1177*3d8817e4Smiod 	  const char * msg = (const char *) 0;
1178*3d8817e4Smiod 
1179*3d8817e4Smiod 	  switch (r)
1180*3d8817e4Smiod 	    {
1181*3d8817e4Smiod 	    case bfd_reloc_overflow:
1182*3d8817e4Smiod 	      if (!((*info->callbacks->reloc_overflow)
1183*3d8817e4Smiod 		    (info, NULL, name, howto->name, (bfd_vma) 0,
1184*3d8817e4Smiod 		     input_bfd, input_section, rel->r_offset)))
1185*3d8817e4Smiod 		return FALSE;
1186*3d8817e4Smiod 	      break;
1187*3d8817e4Smiod 
1188*3d8817e4Smiod 	    case bfd_reloc_undefined:
1189*3d8817e4Smiod 	      if (!((*info->callbacks->undefined_symbol)
1190*3d8817e4Smiod 		    (info, name, input_bfd, input_section,
1191*3d8817e4Smiod 		     rel->r_offset, TRUE)))
1192*3d8817e4Smiod 		return FALSE;
1193*3d8817e4Smiod 	      break;
1194*3d8817e4Smiod 
1195*3d8817e4Smiod 	    case bfd_reloc_outofrange:
1196*3d8817e4Smiod 	      msg = _ ("internal error: out of range error");
1197*3d8817e4Smiod 	      goto common_error;
1198*3d8817e4Smiod 
1199*3d8817e4Smiod 	    case bfd_reloc_notsupported:
1200*3d8817e4Smiod 	      msg = _ ("internal error: unsupported relocation error");
1201*3d8817e4Smiod 	      goto common_error;
1202*3d8817e4Smiod 
1203*3d8817e4Smiod 	    case bfd_reloc_dangerous:
1204*3d8817e4Smiod 	      msg = _ ("internal error: dangerous error");
1205*3d8817e4Smiod 	      goto common_error;
1206*3d8817e4Smiod 
1207*3d8817e4Smiod 	    default:
1208*3d8817e4Smiod 	      msg = _ ("internal error: unknown error");
1209*3d8817e4Smiod 	      /* fall through */
1210*3d8817e4Smiod 
1211*3d8817e4Smiod 	    common_error:
1212*3d8817e4Smiod 	      if (!((*info->callbacks->warning)
1213*3d8817e4Smiod 		    (info, msg, name, input_bfd, input_section,
1214*3d8817e4Smiod 		     rel->r_offset)))
1215*3d8817e4Smiod 		return FALSE;
1216*3d8817e4Smiod 	      break;
1217*3d8817e4Smiod 	    }
1218*3d8817e4Smiod 	}
1219*3d8817e4Smiod     }
1220*3d8817e4Smiod 
1221*3d8817e4Smiod   return TRUE;
1222*3d8817e4Smiod }
1223*3d8817e4Smiod 
1224*3d8817e4Smiod 
1225*3d8817e4Smiod 
1226*3d8817e4Smiod /* Set and control ELF flags in ELF header.  */
1227*3d8817e4Smiod 
1228*3d8817e4Smiod bfd_boolean
_bfd_m68hc11_elf_set_private_flags(bfd * abfd,flagword flags)1229*3d8817e4Smiod _bfd_m68hc11_elf_set_private_flags (bfd *abfd, flagword flags)
1230*3d8817e4Smiod {
1231*3d8817e4Smiod   BFD_ASSERT (!elf_flags_init (abfd)
1232*3d8817e4Smiod 	      || elf_elfheader (abfd)->e_flags == flags);
1233*3d8817e4Smiod 
1234*3d8817e4Smiod   elf_elfheader (abfd)->e_flags = flags;
1235*3d8817e4Smiod   elf_flags_init (abfd) = TRUE;
1236*3d8817e4Smiod   return TRUE;
1237*3d8817e4Smiod }
1238*3d8817e4Smiod 
1239*3d8817e4Smiod /* Merge backend specific data from an object file to the output
1240*3d8817e4Smiod    object file when linking.  */
1241*3d8817e4Smiod 
1242*3d8817e4Smiod bfd_boolean
_bfd_m68hc11_elf_merge_private_bfd_data(bfd * ibfd,bfd * obfd)1243*3d8817e4Smiod _bfd_m68hc11_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
1244*3d8817e4Smiod {
1245*3d8817e4Smiod   flagword old_flags;
1246*3d8817e4Smiod   flagword new_flags;
1247*3d8817e4Smiod   bfd_boolean ok = TRUE;
1248*3d8817e4Smiod 
1249*3d8817e4Smiod   /* Check if we have the same endianess */
1250*3d8817e4Smiod   if (!_bfd_generic_verify_endian_match (ibfd, obfd))
1251*3d8817e4Smiod     return FALSE;
1252*3d8817e4Smiod 
1253*3d8817e4Smiod   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1254*3d8817e4Smiod       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1255*3d8817e4Smiod     return TRUE;
1256*3d8817e4Smiod 
1257*3d8817e4Smiod   new_flags = elf_elfheader (ibfd)->e_flags;
1258*3d8817e4Smiod   elf_elfheader (obfd)->e_flags |= new_flags & EF_M68HC11_ABI;
1259*3d8817e4Smiod   old_flags = elf_elfheader (obfd)->e_flags;
1260*3d8817e4Smiod 
1261*3d8817e4Smiod   if (! elf_flags_init (obfd))
1262*3d8817e4Smiod     {
1263*3d8817e4Smiod       elf_flags_init (obfd) = TRUE;
1264*3d8817e4Smiod       elf_elfheader (obfd)->e_flags = new_flags;
1265*3d8817e4Smiod       elf_elfheader (obfd)->e_ident[EI_CLASS]
1266*3d8817e4Smiod 	= elf_elfheader (ibfd)->e_ident[EI_CLASS];
1267*3d8817e4Smiod 
1268*3d8817e4Smiod       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
1269*3d8817e4Smiod 	  && bfd_get_arch_info (obfd)->the_default)
1270*3d8817e4Smiod 	{
1271*3d8817e4Smiod 	  if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
1272*3d8817e4Smiod 				   bfd_get_mach (ibfd)))
1273*3d8817e4Smiod 	    return FALSE;
1274*3d8817e4Smiod 	}
1275*3d8817e4Smiod 
1276*3d8817e4Smiod       return TRUE;
1277*3d8817e4Smiod     }
1278*3d8817e4Smiod 
1279*3d8817e4Smiod   /* Check ABI compatibility.  */
1280*3d8817e4Smiod   if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
1281*3d8817e4Smiod     {
1282*3d8817e4Smiod       (*_bfd_error_handler)
1283*3d8817e4Smiod 	(_("%B: linking files compiled for 16-bit integers (-mshort) "
1284*3d8817e4Smiod            "and others for 32-bit integers"), ibfd);
1285*3d8817e4Smiod       ok = FALSE;
1286*3d8817e4Smiod     }
1287*3d8817e4Smiod   if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
1288*3d8817e4Smiod     {
1289*3d8817e4Smiod       (*_bfd_error_handler)
1290*3d8817e4Smiod 	(_("%B: linking files compiled for 32-bit double (-fshort-double) "
1291*3d8817e4Smiod            "and others for 64-bit double"), ibfd);
1292*3d8817e4Smiod       ok = FALSE;
1293*3d8817e4Smiod     }
1294*3d8817e4Smiod 
1295*3d8817e4Smiod   /* Processor compatibility.  */
1296*3d8817e4Smiod   if (!EF_M68HC11_CAN_MERGE_MACH (new_flags, old_flags))
1297*3d8817e4Smiod     {
1298*3d8817e4Smiod       (*_bfd_error_handler)
1299*3d8817e4Smiod 	(_("%B: linking files compiled for HCS12 with "
1300*3d8817e4Smiod            "others compiled for HC12"), ibfd);
1301*3d8817e4Smiod       ok = FALSE;
1302*3d8817e4Smiod     }
1303*3d8817e4Smiod   new_flags = ((new_flags & ~EF_M68HC11_MACH_MASK)
1304*3d8817e4Smiod                | (EF_M68HC11_MERGE_MACH (new_flags, old_flags)));
1305*3d8817e4Smiod 
1306*3d8817e4Smiod   elf_elfheader (obfd)->e_flags = new_flags;
1307*3d8817e4Smiod 
1308*3d8817e4Smiod   new_flags &= ~(EF_M68HC11_ABI | EF_M68HC11_MACH_MASK);
1309*3d8817e4Smiod   old_flags &= ~(EF_M68HC11_ABI | EF_M68HC11_MACH_MASK);
1310*3d8817e4Smiod 
1311*3d8817e4Smiod   /* Warn about any other mismatches */
1312*3d8817e4Smiod   if (new_flags != old_flags)
1313*3d8817e4Smiod     {
1314*3d8817e4Smiod       (*_bfd_error_handler)
1315*3d8817e4Smiod 	(_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
1316*3d8817e4Smiod 	 ibfd, (unsigned long) new_flags, (unsigned long) old_flags);
1317*3d8817e4Smiod       ok = FALSE;
1318*3d8817e4Smiod     }
1319*3d8817e4Smiod 
1320*3d8817e4Smiod   if (! ok)
1321*3d8817e4Smiod     {
1322*3d8817e4Smiod       bfd_set_error (bfd_error_bad_value);
1323*3d8817e4Smiod       return FALSE;
1324*3d8817e4Smiod     }
1325*3d8817e4Smiod 
1326*3d8817e4Smiod   return TRUE;
1327*3d8817e4Smiod }
1328*3d8817e4Smiod 
1329*3d8817e4Smiod bfd_boolean
_bfd_m68hc11_elf_print_private_bfd_data(bfd * abfd,void * ptr)1330*3d8817e4Smiod _bfd_m68hc11_elf_print_private_bfd_data (bfd *abfd, void *ptr)
1331*3d8817e4Smiod {
1332*3d8817e4Smiod   FILE *file = (FILE *) ptr;
1333*3d8817e4Smiod 
1334*3d8817e4Smiod   BFD_ASSERT (abfd != NULL && ptr != NULL);
1335*3d8817e4Smiod 
1336*3d8817e4Smiod   /* Print normal ELF private data.  */
1337*3d8817e4Smiod   _bfd_elf_print_private_bfd_data (abfd, ptr);
1338*3d8817e4Smiod 
1339*3d8817e4Smiod   /* xgettext:c-format */
1340*3d8817e4Smiod   fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
1341*3d8817e4Smiod 
1342*3d8817e4Smiod   if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
1343*3d8817e4Smiod     fprintf (file, _("[abi=32-bit int, "));
1344*3d8817e4Smiod   else
1345*3d8817e4Smiod     fprintf (file, _("[abi=16-bit int, "));
1346*3d8817e4Smiod 
1347*3d8817e4Smiod   if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
1348*3d8817e4Smiod     fprintf (file, _("64-bit double, "));
1349*3d8817e4Smiod   else
1350*3d8817e4Smiod     fprintf (file, _("32-bit double, "));
1351*3d8817e4Smiod 
1352*3d8817e4Smiod   if (strcmp (bfd_get_target (abfd), "elf32-m68hc11") == 0)
1353*3d8817e4Smiod     fprintf (file, _("cpu=HC11]"));
1354*3d8817e4Smiod   else if (elf_elfheader (abfd)->e_flags & EF_M68HCS12_MACH)
1355*3d8817e4Smiod     fprintf (file, _("cpu=HCS12]"));
1356*3d8817e4Smiod   else
1357*3d8817e4Smiod     fprintf (file, _("cpu=HC12]"));
1358*3d8817e4Smiod 
1359*3d8817e4Smiod   if (elf_elfheader (abfd)->e_flags & E_M68HC12_BANKS)
1360*3d8817e4Smiod     fprintf (file, _(" [memory=bank-model]"));
1361*3d8817e4Smiod   else
1362*3d8817e4Smiod     fprintf (file, _(" [memory=flat]"));
1363*3d8817e4Smiod 
1364*3d8817e4Smiod   fputc ('\n', file);
1365*3d8817e4Smiod 
1366*3d8817e4Smiod   return TRUE;
1367*3d8817e4Smiod }
1368*3d8817e4Smiod 
scan_sections_for_abi(bfd * abfd ATTRIBUTE_UNUSED,asection * asect,void * arg)1369*3d8817e4Smiod static void scan_sections_for_abi (bfd *abfd ATTRIBUTE_UNUSED,
1370*3d8817e4Smiod                                    asection *asect, void *arg)
1371*3d8817e4Smiod {
1372*3d8817e4Smiod   struct m68hc11_scan_param* p = (struct m68hc11_scan_param*) arg;
1373*3d8817e4Smiod 
1374*3d8817e4Smiod   if (asect->vma >= p->pinfo->bank_virtual)
1375*3d8817e4Smiod     p->use_memory_banks = TRUE;
1376*3d8817e4Smiod }
1377*3d8817e4Smiod 
1378*3d8817e4Smiod /* Tweak the OSABI field of the elf header.  */
1379*3d8817e4Smiod 
1380*3d8817e4Smiod void
elf32_m68hc11_post_process_headers(bfd * abfd,struct bfd_link_info * link_info)1381*3d8817e4Smiod elf32_m68hc11_post_process_headers (bfd *abfd, struct bfd_link_info *link_info)
1382*3d8817e4Smiod {
1383*3d8817e4Smiod   struct m68hc11_scan_param param;
1384*3d8817e4Smiod 
1385*3d8817e4Smiod   if (link_info == 0)
1386*3d8817e4Smiod     return;
1387*3d8817e4Smiod 
1388*3d8817e4Smiod   m68hc11_elf_get_bank_parameters (link_info);
1389*3d8817e4Smiod 
1390*3d8817e4Smiod   param.use_memory_banks = FALSE;
1391*3d8817e4Smiod   param.pinfo = &m68hc11_elf_hash_table (link_info)->pinfo;
1392*3d8817e4Smiod   bfd_map_over_sections (abfd, scan_sections_for_abi, &param);
1393*3d8817e4Smiod   if (param.use_memory_banks)
1394*3d8817e4Smiod     {
1395*3d8817e4Smiod       Elf_Internal_Ehdr * i_ehdrp;
1396*3d8817e4Smiod 
1397*3d8817e4Smiod       i_ehdrp = elf_elfheader (abfd);
1398*3d8817e4Smiod       i_ehdrp->e_flags |= E_M68HC12_BANKS;
1399*3d8817e4Smiod     }
1400*3d8817e4Smiod }
1401*3d8817e4Smiod 
1402