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