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