Back to index

cell-binutils  2.17cvs20070401
elf32-m68hc1x.c
Go to the documentation of this file.
00001 /* Motorola 68HC11/HC12-specific support for 32-bit ELF
00002    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
00003    Free Software Foundation, Inc.
00004    Contributed by Stephane Carrez (stcarrez@nerim.fr)
00005 
00006 This file is part of BFD, the Binary File Descriptor library.
00007 
00008 This program is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with this program; if not, write to the Free Software
00020 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 #include "bfd.h"
00023 #include "sysdep.h"
00024 #include "bfdlink.h"
00025 #include "libbfd.h"
00026 #include "elf-bfd.h"
00027 #include "elf32-m68hc1x.h"
00028 #include "elf/m68hc11.h"
00029 #include "opcode/m68hc11.h"
00030 
00031 
00032 #define m68hc12_stub_hash_lookup(table, string, create, copy) \
00033   ((struct elf32_m68hc11_stub_hash_entry *) \
00034    bfd_hash_lookup ((table), (string), (create), (copy)))
00035 
00036 static struct elf32_m68hc11_stub_hash_entry* m68hc12_add_stub
00037   (const char *stub_name,
00038    asection *section,
00039    struct m68hc11_elf_link_hash_table *htab);
00040 
00041 static struct bfd_hash_entry *stub_hash_newfunc
00042   (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
00043 
00044 static void m68hc11_elf_set_symbol (bfd* abfd, struct bfd_link_info *info,
00045                                     const char* name, bfd_vma value,
00046                                     asection* sec);
00047 
00048 static bfd_boolean m68hc11_elf_export_one_stub
00049   (struct bfd_hash_entry *gen_entry, void *in_arg);
00050 
00051 static void scan_sections_for_abi (bfd*, asection*, PTR);
00052 
00053 struct m68hc11_scan_param
00054 {
00055    struct m68hc11_page_info* pinfo;
00056    bfd_boolean use_memory_banks;
00057 };
00058 
00059 
00060 /* Create a 68HC11/68HC12 ELF linker hash table.  */
00061 
00062 struct m68hc11_elf_link_hash_table*
00063 m68hc11_elf_hash_table_create (bfd *abfd)
00064 {
00065   struct m68hc11_elf_link_hash_table *ret;
00066   bfd_size_type amt = sizeof (struct m68hc11_elf_link_hash_table);
00067 
00068   ret = (struct m68hc11_elf_link_hash_table *) bfd_malloc (amt);
00069   if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
00070     return NULL;
00071 
00072   memset (ret, 0, amt);
00073   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
00074                                   _bfd_elf_link_hash_newfunc,
00075                                   sizeof (struct elf_link_hash_entry)))
00076     {
00077       free (ret);
00078       return NULL;
00079     }
00080 
00081   /* Init the stub hash table too.  */
00082   amt = sizeof (struct bfd_hash_table);
00083   ret->stub_hash_table = (struct bfd_hash_table*) bfd_malloc (amt);
00084   if (ret->stub_hash_table == NULL)
00085     {
00086       free (ret);
00087       return NULL;
00088     }
00089   if (!bfd_hash_table_init (ret->stub_hash_table, stub_hash_newfunc,
00090                          sizeof (struct elf32_m68hc11_stub_hash_entry)))
00091     return NULL;
00092 
00093   ret->stub_bfd = NULL;
00094   ret->stub_section = 0;
00095   ret->add_stub_section = NULL;
00096   ret->sym_sec.abfd = NULL;
00097 
00098   return ret;
00099 }
00100 
00101 /* Free the derived linker hash table.  */
00102 
00103 void
00104 m68hc11_elf_bfd_link_hash_table_free (struct bfd_link_hash_table *hash)
00105 {
00106   struct m68hc11_elf_link_hash_table *ret
00107     = (struct m68hc11_elf_link_hash_table *) hash;
00108 
00109   bfd_hash_table_free (ret->stub_hash_table);
00110   free (ret->stub_hash_table);
00111   _bfd_generic_link_hash_table_free (hash);
00112 }
00113 
00114 /* Assorted hash table functions.  */
00115 
00116 /* Initialize an entry in the stub hash table.  */
00117 
00118 static struct bfd_hash_entry *
00119 stub_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table,
00120                    const char *string)
00121 {
00122   /* Allocate the structure if it has not already been allocated by a
00123      subclass.  */
00124   if (entry == NULL)
00125     {
00126       entry = bfd_hash_allocate (table,
00127                              sizeof (struct elf32_m68hc11_stub_hash_entry));
00128       if (entry == NULL)
00129        return entry;
00130     }
00131 
00132   /* Call the allocation method of the superclass.  */
00133   entry = bfd_hash_newfunc (entry, table, string);
00134   if (entry != NULL)
00135     {
00136       struct elf32_m68hc11_stub_hash_entry *eh;
00137 
00138       /* Initialize the local fields.  */
00139       eh = (struct elf32_m68hc11_stub_hash_entry *) entry;
00140       eh->stub_sec = NULL;
00141       eh->stub_offset = 0;
00142       eh->target_value = 0;
00143       eh->target_section = NULL;
00144     }
00145 
00146   return entry;
00147 }
00148 
00149 /* Add a new stub entry to the stub hash.  Not all fields of the new
00150    stub entry are initialised.  */
00151 
00152 static struct elf32_m68hc11_stub_hash_entry *
00153 m68hc12_add_stub (const char *stub_name, asection *section,
00154                   struct m68hc11_elf_link_hash_table *htab)
00155 {
00156   struct elf32_m68hc11_stub_hash_entry *stub_entry;
00157 
00158   /* Enter this entry into the linker stub hash table.  */
00159   stub_entry = m68hc12_stub_hash_lookup (htab->stub_hash_table, stub_name,
00160                                          TRUE, FALSE);
00161   if (stub_entry == NULL)
00162     {
00163       (*_bfd_error_handler) (_("%B: cannot create stub entry %s"),
00164                           section->owner, stub_name);
00165       return NULL;
00166     }
00167 
00168   if (htab->stub_section == 0)
00169     {
00170       htab->stub_section = (*htab->add_stub_section) (".tramp",
00171                                                       htab->tramp_section);
00172     }
00173 
00174   stub_entry->stub_sec = htab->stub_section;
00175   stub_entry->stub_offset = 0;
00176   return stub_entry;
00177 }
00178 
00179 /* Hook called by the linker routine which adds symbols from an object
00180    file.  We use it for identify far symbols and force a loading of
00181    the trampoline handler.  */
00182 
00183 bfd_boolean
00184 elf32_m68hc11_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
00185                                Elf_Internal_Sym *sym,
00186                                const char **namep ATTRIBUTE_UNUSED,
00187                                flagword *flagsp ATTRIBUTE_UNUSED,
00188                                asection **secp ATTRIBUTE_UNUSED,
00189                                bfd_vma *valp ATTRIBUTE_UNUSED)
00190 {
00191   if (sym->st_other & STO_M68HC12_FAR)
00192     {
00193       struct elf_link_hash_entry *h;
00194 
00195       h = (struct elf_link_hash_entry *)
00196        bfd_link_hash_lookup (info->hash, "__far_trampoline",
00197                               FALSE, FALSE, FALSE);
00198       if (h == NULL)
00199         {
00200           struct bfd_link_hash_entry* entry = NULL;
00201 
00202           _bfd_generic_link_add_one_symbol (info, abfd,
00203                                             "__far_trampoline",
00204                                             BSF_GLOBAL,
00205                                             bfd_und_section_ptr,
00206                                             (bfd_vma) 0, (const char*) NULL,
00207                                             FALSE, FALSE, &entry);
00208         }
00209 
00210     }
00211   return TRUE;
00212 }
00213 
00214 /* External entry points for sizing and building linker stubs.  */
00215 
00216 /* Set up various things so that we can make a list of input sections
00217    for each output section included in the link.  Returns -1 on error,
00218    0 when no stubs will be needed, and 1 on success.  */
00219 
00220 int
00221 elf32_m68hc11_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info)
00222 {
00223   bfd *input_bfd;
00224   unsigned int bfd_count;
00225   int top_id, top_index;
00226   asection *section;
00227   asection **input_list, **list;
00228   bfd_size_type amt;
00229   asection *text_section;
00230   struct m68hc11_elf_link_hash_table *htab;
00231 
00232   htab = m68hc11_elf_hash_table (info);
00233 
00234   if (htab->root.root.creator->flavour != bfd_target_elf_flavour)
00235     return 0;
00236 
00237   /* Count the number of input BFDs and find the top input section id.
00238      Also search for an existing ".tramp" section so that we know
00239      where generated trampolines must go.  Default to ".text" if we
00240      can't find it.  */
00241   htab->tramp_section = 0;
00242   text_section = 0;
00243   for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
00244        input_bfd != NULL;
00245        input_bfd = input_bfd->link_next)
00246     {
00247       bfd_count += 1;
00248       for (section = input_bfd->sections;
00249           section != NULL;
00250           section = section->next)
00251        {
00252           const char* name = bfd_get_section_name (input_bfd, section);
00253 
00254           if (!strcmp (name, ".tramp"))
00255             htab->tramp_section = section;
00256 
00257           if (!strcmp (name, ".text"))
00258             text_section = section;
00259 
00260          if (top_id < section->id)
00261            top_id = section->id;
00262        }
00263     }
00264   htab->bfd_count = bfd_count;
00265   if (htab->tramp_section == 0)
00266     htab->tramp_section = text_section;
00267 
00268   /* We can't use output_bfd->section_count here to find the top output
00269      section index as some sections may have been removed, and
00270      strip_excluded_output_sections doesn't renumber the indices.  */
00271   for (section = output_bfd->sections, top_index = 0;
00272        section != NULL;
00273        section = section->next)
00274     {
00275       if (top_index < section->index)
00276        top_index = section->index;
00277     }
00278 
00279   htab->top_index = top_index;
00280   amt = sizeof (asection *) * (top_index + 1);
00281   input_list = (asection **) bfd_malloc (amt);
00282   htab->input_list = input_list;
00283   if (input_list == NULL)
00284     return -1;
00285 
00286   /* For sections we aren't interested in, mark their entries with a
00287      value we can check later.  */
00288   list = input_list + top_index;
00289   do
00290     *list = bfd_abs_section_ptr;
00291   while (list-- != input_list);
00292 
00293   for (section = output_bfd->sections;
00294        section != NULL;
00295        section = section->next)
00296     {
00297       if ((section->flags & SEC_CODE) != 0)
00298        input_list[section->index] = NULL;
00299     }
00300 
00301   return 1;
00302 }
00303 
00304 /* Determine and set the size of the stub section for a final link.
00305 
00306    The basic idea here is to examine all the relocations looking for
00307    PC-relative calls to a target that is unreachable with a "bl"
00308    instruction.  */
00309 
00310 bfd_boolean
00311 elf32_m68hc11_size_stubs (bfd *output_bfd, bfd *stub_bfd,
00312                           struct bfd_link_info *info,
00313                           asection * (*add_stub_section) (const char*, asection*))
00314 {
00315   bfd *input_bfd;
00316   asection *section;
00317   Elf_Internal_Sym *local_syms, **all_local_syms;
00318   unsigned int bfd_indx, bfd_count;
00319   bfd_size_type amt;
00320   asection *stub_sec;
00321 
00322   struct m68hc11_elf_link_hash_table *htab = m68hc11_elf_hash_table (info);
00323 
00324   /* Stash our params away.  */
00325   htab->stub_bfd = stub_bfd;
00326   htab->add_stub_section = add_stub_section;
00327 
00328   /* Count the number of input BFDs and find the top input section id.  */
00329   for (input_bfd = info->input_bfds, bfd_count = 0;
00330        input_bfd != NULL;
00331        input_bfd = input_bfd->link_next)
00332     {
00333       bfd_count += 1;
00334     }
00335 
00336   /* We want to read in symbol extension records only once.  To do this
00337      we need to read in the local symbols in parallel and save them for
00338      later use; so hold pointers to the local symbols in an array.  */
00339   amt = sizeof (Elf_Internal_Sym *) * bfd_count;
00340   all_local_syms = (Elf_Internal_Sym **) bfd_zmalloc (amt);
00341   if (all_local_syms == NULL)
00342     return FALSE;
00343 
00344   /* Walk over all the input BFDs, swapping in local symbols.  */
00345   for (input_bfd = info->input_bfds, bfd_indx = 0;
00346        input_bfd != NULL;
00347        input_bfd = input_bfd->link_next, bfd_indx++)
00348     {
00349       Elf_Internal_Shdr *symtab_hdr;
00350 
00351       /* We'll need the symbol table in a second.  */
00352       symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
00353       if (symtab_hdr->sh_info == 0)
00354        continue;
00355 
00356       /* We need an array of the local symbols attached to the input bfd.  */
00357       local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
00358       if (local_syms == NULL)
00359        {
00360          local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
00361                                         symtab_hdr->sh_info, 0,
00362                                         NULL, NULL, NULL);
00363          /* Cache them for elf_link_input_bfd.  */
00364          symtab_hdr->contents = (unsigned char *) local_syms;
00365        }
00366       if (local_syms == NULL)
00367         {
00368           free (all_local_syms);
00369          return FALSE;
00370         }
00371 
00372       all_local_syms[bfd_indx] = local_syms;
00373     }
00374 
00375   for (input_bfd = info->input_bfds, bfd_indx = 0;
00376        input_bfd != NULL;
00377        input_bfd = input_bfd->link_next, bfd_indx++)
00378     {
00379       Elf_Internal_Shdr *symtab_hdr;
00380       Elf_Internal_Sym *local_syms;
00381       struct elf_link_hash_entry ** sym_hashes;
00382 
00383       sym_hashes = elf_sym_hashes (input_bfd);
00384 
00385       /* We'll need the symbol table in a second.  */
00386       symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
00387       if (symtab_hdr->sh_info == 0)
00388         continue;
00389 
00390       local_syms = all_local_syms[bfd_indx];
00391 
00392       /* Walk over each section attached to the input bfd.  */
00393       for (section = input_bfd->sections;
00394            section != NULL;
00395            section = section->next)
00396         {
00397           Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
00398 
00399           /* If there aren't any relocs, then there's nothing more
00400              to do.  */
00401           if ((section->flags & SEC_RELOC) == 0
00402               || section->reloc_count == 0)
00403             continue;
00404 
00405           /* If this section is a link-once section that will be
00406              discarded, then don't create any stubs.  */
00407           if (section->output_section == NULL
00408               || section->output_section->owner != output_bfd)
00409             continue;
00410 
00411           /* Get the relocs.  */
00412           internal_relocs
00413             = _bfd_elf_link_read_relocs (input_bfd, section, NULL,
00414                                     (Elf_Internal_Rela *) NULL,
00415                                     info->keep_memory);
00416           if (internal_relocs == NULL)
00417             goto error_ret_free_local;
00418 
00419           /* Now examine each relocation.  */
00420           irela = internal_relocs;
00421           irelaend = irela + section->reloc_count;
00422           for (; irela < irelaend; irela++)
00423             {
00424               unsigned int r_type, r_indx;
00425               struct elf32_m68hc11_stub_hash_entry *stub_entry;
00426               asection *sym_sec;
00427               bfd_vma sym_value;
00428               struct elf_link_hash_entry *hash;
00429               const char *stub_name;
00430               Elf_Internal_Sym *sym;
00431 
00432               r_type = ELF32_R_TYPE (irela->r_info);
00433 
00434               /* Only look at 16-bit relocs.  */
00435               if (r_type != (unsigned int) R_M68HC11_16)
00436                 continue;
00437 
00438               /* Now determine the call target, its name, value,
00439                  section.  */
00440               r_indx = ELF32_R_SYM (irela->r_info);
00441               if (r_indx < symtab_hdr->sh_info)
00442                 {
00443                   /* It's a local symbol.  */
00444                   Elf_Internal_Shdr *hdr;
00445                   bfd_boolean is_far;
00446 
00447                   sym = local_syms + r_indx;
00448                   is_far = (sym && (sym->st_other & STO_M68HC12_FAR));
00449                   if (!is_far)
00450                     continue;
00451 
00452                   hdr = elf_elfsections (input_bfd)[sym->st_shndx];
00453                   sym_sec = hdr->bfd_section;
00454                   stub_name = (bfd_elf_string_from_elf_section
00455                                (input_bfd, symtab_hdr->sh_link,
00456                                 sym->st_name));
00457                   sym_value = sym->st_value;
00458                   hash = NULL;
00459                 }
00460               else
00461                 {
00462                   /* It's an external symbol.  */
00463                   int e_indx;
00464 
00465                   e_indx = r_indx - symtab_hdr->sh_info;
00466                   hash = (struct elf_link_hash_entry *)
00467                     (sym_hashes[e_indx]);
00468 
00469                   while (hash->root.type == bfd_link_hash_indirect
00470                          || hash->root.type == bfd_link_hash_warning)
00471                     hash = ((struct elf_link_hash_entry *)
00472                             hash->root.u.i.link);
00473 
00474                   if (hash->root.type == bfd_link_hash_defined
00475                       || hash->root.type == bfd_link_hash_defweak
00476                       || hash->root.type == bfd_link_hash_new)
00477                     {
00478                       if (!(hash->other & STO_M68HC12_FAR))
00479                         continue;
00480                     }
00481                   else if (hash->root.type == bfd_link_hash_undefweak)
00482                     {
00483                       continue;
00484                     }
00485                   else if (hash->root.type == bfd_link_hash_undefined)
00486                     {
00487                       continue;
00488                     }
00489                   else
00490                     {
00491                       bfd_set_error (bfd_error_bad_value);
00492                       goto error_ret_free_internal;
00493                     }
00494                   sym_sec = hash->root.u.def.section;
00495                   sym_value = hash->root.u.def.value;
00496                   stub_name = hash->root.root.string;
00497                 }
00498 
00499               if (!stub_name)
00500                 goto error_ret_free_internal;
00501 
00502               stub_entry = m68hc12_stub_hash_lookup
00503                 (htab->stub_hash_table,
00504                  stub_name,
00505                  FALSE, FALSE);
00506               if (stub_entry == NULL)
00507                 {
00508                   if (add_stub_section == 0)
00509                     continue;
00510 
00511                   stub_entry = m68hc12_add_stub (stub_name, section, htab);
00512                   if (stub_entry == NULL)
00513                     {
00514                     error_ret_free_internal:
00515                       if (elf_section_data (section)->relocs == NULL)
00516                         free (internal_relocs);
00517                       goto error_ret_free_local;
00518                     }
00519                 }
00520 
00521               stub_entry->target_value = sym_value;
00522               stub_entry->target_section = sym_sec;
00523             }
00524 
00525           /* We're done with the internal relocs, free them.  */
00526           if (elf_section_data (section)->relocs == NULL)
00527             free (internal_relocs);
00528         }
00529     }
00530 
00531   if (add_stub_section)
00532     {
00533       /* OK, we've added some stubs.  Find out the new size of the
00534          stub sections.  */
00535       for (stub_sec = htab->stub_bfd->sections;
00536            stub_sec != NULL;
00537            stub_sec = stub_sec->next)
00538         {
00539           stub_sec->size = 0;
00540         }
00541 
00542       bfd_hash_traverse (htab->stub_hash_table, htab->size_one_stub, htab);
00543     }
00544   free (all_local_syms);
00545   return TRUE;
00546 
00547  error_ret_free_local:
00548   free (all_local_syms);
00549   return FALSE;
00550 }
00551 
00552 /* Export the trampoline addresses in the symbol table.  */
00553 static bfd_boolean
00554 m68hc11_elf_export_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
00555 {
00556   struct bfd_link_info *info;
00557   struct m68hc11_elf_link_hash_table *htab;
00558   struct elf32_m68hc11_stub_hash_entry *stub_entry;
00559   char* name;
00560   bfd_boolean result;
00561 
00562   info = (struct bfd_link_info *) in_arg;
00563   htab = m68hc11_elf_hash_table (info);
00564 
00565   /* Massage our args to the form they really have.  */
00566   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
00567 
00568   /* Generate the trampoline according to HC11 or HC12.  */
00569   result = (* htab->build_one_stub) (gen_entry, in_arg);
00570 
00571   /* Make a printable name that does not conflict with the real function.  */
00572   name = alloca (strlen (stub_entry->root.string) + 16);
00573   sprintf (name, "tramp.%s", stub_entry->root.string);
00574 
00575   /* Export the symbol for debugging/disassembling.  */
00576   m68hc11_elf_set_symbol (htab->stub_bfd, info, name,
00577                           stub_entry->stub_offset,
00578                           stub_entry->stub_sec);
00579   return result;
00580 }
00581 
00582 /* Export a symbol or set its value and section.  */
00583 static void
00584 m68hc11_elf_set_symbol (bfd *abfd, struct bfd_link_info *info,
00585                         const char *name, bfd_vma value, asection *sec)
00586 {
00587   struct elf_link_hash_entry *h;
00588 
00589   h = (struct elf_link_hash_entry *)
00590     bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, FALSE);
00591   if (h == NULL)
00592     {
00593       _bfd_generic_link_add_one_symbol (info, abfd,
00594                                         name,
00595                                         BSF_GLOBAL,
00596                                         sec,
00597                                         value,
00598                                         (const char*) NULL,
00599                                         TRUE, FALSE, NULL);
00600     }
00601   else
00602     {
00603       h->root.type = bfd_link_hash_defined;
00604       h->root.u.def.value = value;
00605       h->root.u.def.section = sec;
00606     }
00607 }
00608 
00609 
00610 /* Build all the stubs associated with the current output file.  The
00611    stubs are kept in a hash table attached to the main linker hash
00612    table.  This function is called via m68hc12elf_finish in the
00613    linker.  */
00614 
00615 bfd_boolean
00616 elf32_m68hc11_build_stubs (bfd *abfd, struct bfd_link_info *info)
00617 {
00618   asection *stub_sec;
00619   struct bfd_hash_table *table;
00620   struct m68hc11_elf_link_hash_table *htab;
00621   struct m68hc11_scan_param param;
00622 
00623   m68hc11_elf_get_bank_parameters (info);
00624   htab = m68hc11_elf_hash_table (info);
00625 
00626   for (stub_sec = htab->stub_bfd->sections;
00627        stub_sec != NULL;
00628        stub_sec = stub_sec->next)
00629     {
00630       bfd_size_type size;
00631 
00632       /* Allocate memory to hold the linker stubs.  */
00633       size = stub_sec->size;
00634       stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, size);
00635       if (stub_sec->contents == NULL && size != 0)
00636        return FALSE;
00637       stub_sec->size = 0;
00638     }
00639 
00640   /* Build the stubs as directed by the stub hash table.  */
00641   table = htab->stub_hash_table;
00642   bfd_hash_traverse (table, m68hc11_elf_export_one_stub, info);
00643   
00644   /* Scan the output sections to see if we use the memory banks.
00645      If so, export the symbols that define how the memory banks
00646      are mapped.  This is used by gdb and the simulator to obtain
00647      the information.  It can be used by programs to burn the eprom
00648      at the good addresses.  */
00649   param.use_memory_banks = FALSE;
00650   param.pinfo = &htab->pinfo;
00651   bfd_map_over_sections (abfd, scan_sections_for_abi, &param);
00652   if (param.use_memory_banks)
00653     {
00654       m68hc11_elf_set_symbol (abfd, info, BFD_M68HC11_BANK_START_NAME,
00655                               htab->pinfo.bank_physical,
00656                               bfd_abs_section_ptr);
00657       m68hc11_elf_set_symbol (abfd, info, BFD_M68HC11_BANK_VIRTUAL_NAME,
00658                               htab->pinfo.bank_virtual,
00659                               bfd_abs_section_ptr);
00660       m68hc11_elf_set_symbol (abfd, info, BFD_M68HC11_BANK_SIZE_NAME,
00661                               htab->pinfo.bank_size,
00662                               bfd_abs_section_ptr);
00663     }
00664 
00665   return TRUE;
00666 }
00667 
00668 void
00669 m68hc11_elf_get_bank_parameters (struct bfd_link_info *info)
00670 {
00671   unsigned i;
00672   struct m68hc11_page_info *pinfo;
00673   struct bfd_link_hash_entry *h;
00674 
00675   pinfo = &m68hc11_elf_hash_table (info)->pinfo;
00676   if (pinfo->bank_param_initialized)
00677     return;
00678 
00679   pinfo->bank_virtual = M68HC12_BANK_VIRT;
00680   pinfo->bank_mask = M68HC12_BANK_MASK;
00681   pinfo->bank_physical = M68HC12_BANK_BASE;
00682   pinfo->bank_shift = M68HC12_BANK_SHIFT;
00683   pinfo->bank_size = 1 << M68HC12_BANK_SHIFT;
00684 
00685   h = bfd_link_hash_lookup (info->hash, BFD_M68HC11_BANK_START_NAME,
00686                             FALSE, FALSE, TRUE);
00687   if (h != (struct bfd_link_hash_entry*) NULL
00688       && h->type == bfd_link_hash_defined)
00689     pinfo->bank_physical = (h->u.def.value
00690                             + h->u.def.section->output_section->vma
00691                             + h->u.def.section->output_offset);
00692 
00693   h = bfd_link_hash_lookup (info->hash, BFD_M68HC11_BANK_VIRTUAL_NAME,
00694                             FALSE, FALSE, TRUE);
00695   if (h != (struct bfd_link_hash_entry*) NULL
00696       && h->type == bfd_link_hash_defined)
00697     pinfo->bank_virtual = (h->u.def.value
00698                            + h->u.def.section->output_section->vma
00699                            + h->u.def.section->output_offset);
00700 
00701   h = bfd_link_hash_lookup (info->hash, BFD_M68HC11_BANK_SIZE_NAME,
00702                             FALSE, FALSE, TRUE);
00703   if (h != (struct bfd_link_hash_entry*) NULL
00704       && h->type == bfd_link_hash_defined)
00705     pinfo->bank_size = (h->u.def.value
00706                         + h->u.def.section->output_section->vma
00707                         + h->u.def.section->output_offset);
00708 
00709   pinfo->bank_shift = 0;
00710   for (i = pinfo->bank_size; i != 0; i >>= 1)
00711     pinfo->bank_shift++;
00712   pinfo->bank_shift--;
00713   pinfo->bank_mask = (1 << pinfo->bank_shift) - 1;
00714   pinfo->bank_physical_end = pinfo->bank_physical + pinfo->bank_size;
00715   pinfo->bank_param_initialized = 1;
00716 
00717   h = bfd_link_hash_lookup (info->hash, "__far_trampoline", FALSE,
00718                             FALSE, TRUE);
00719   if (h != (struct bfd_link_hash_entry*) NULL
00720       && h->type == bfd_link_hash_defined)
00721     pinfo->trampoline_addr = (h->u.def.value
00722                               + h->u.def.section->output_section->vma
00723                               + h->u.def.section->output_offset);
00724 }
00725 
00726 /* Return 1 if the address is in banked memory.
00727    This can be applied to a virtual address and to a physical address.  */
00728 int
00729 m68hc11_addr_is_banked (struct m68hc11_page_info *pinfo, bfd_vma addr)
00730 {
00731   if (addr >= pinfo->bank_virtual)
00732     return 1;
00733 
00734   if (addr >= pinfo->bank_physical && addr <= pinfo->bank_physical_end)
00735     return 1;
00736 
00737   return 0;
00738 }
00739 
00740 /* Return the physical address seen by the processor, taking
00741    into account banked memory.  */
00742 bfd_vma
00743 m68hc11_phys_addr (struct m68hc11_page_info *pinfo, bfd_vma addr)
00744 {
00745   if (addr < pinfo->bank_virtual)
00746     return addr;
00747 
00748   /* Map the address to the memory bank.  */
00749   addr -= pinfo->bank_virtual;
00750   addr &= pinfo->bank_mask;
00751   addr += pinfo->bank_physical;
00752   return addr;
00753 }
00754 
00755 /* Return the page number corresponding to an address in banked memory.  */
00756 bfd_vma
00757 m68hc11_phys_page (struct m68hc11_page_info *pinfo, bfd_vma addr)
00758 {
00759   if (addr < pinfo->bank_virtual)
00760     return 0;
00761 
00762   /* Map the address to the memory bank.  */
00763   addr -= pinfo->bank_virtual;
00764   addr >>= pinfo->bank_shift;
00765   addr &= 0x0ff;
00766   return addr;
00767 }
00768 
00769 /* This function is used for relocs which are only used for relaxing,
00770    which the linker should otherwise ignore.  */
00771 
00772 bfd_reloc_status_type
00773 m68hc11_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
00774                           arelent *reloc_entry,
00775                           asymbol *symbol ATTRIBUTE_UNUSED,
00776                           void *data ATTRIBUTE_UNUSED,
00777                           asection *input_section,
00778                           bfd *output_bfd,
00779                           char **error_message ATTRIBUTE_UNUSED)
00780 {
00781   if (output_bfd != NULL)
00782     reloc_entry->address += input_section->output_offset;
00783   return bfd_reloc_ok;
00784 }
00785 
00786 bfd_reloc_status_type
00787 m68hc11_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
00788                            arelent *reloc_entry,
00789                            asymbol *symbol,
00790                            void *data ATTRIBUTE_UNUSED,
00791                            asection *input_section,
00792                            bfd *output_bfd,
00793                            char **error_message ATTRIBUTE_UNUSED)
00794 {
00795   if (output_bfd != (bfd *) NULL
00796       && (symbol->flags & BSF_SECTION_SYM) == 0
00797       && (! reloc_entry->howto->partial_inplace
00798          || reloc_entry->addend == 0))
00799     {
00800       reloc_entry->address += input_section->output_offset;
00801       return bfd_reloc_ok;
00802     }
00803 
00804   if (output_bfd != NULL)
00805     return bfd_reloc_continue;
00806 
00807   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
00808     return bfd_reloc_outofrange;
00809 
00810   abort();
00811 }
00812 
00813 /* Look through the relocs for a section during the first phase.
00814    Since we don't do .gots or .plts, we just need to consider the
00815    virtual table relocs for gc.  */
00816 
00817 bfd_boolean
00818 elf32_m68hc11_check_relocs (bfd *abfd, struct bfd_link_info *info,
00819                             asection *sec, const Elf_Internal_Rela *relocs)
00820 {
00821   Elf_Internal_Shdr *           symtab_hdr;
00822   struct elf_link_hash_entry ** sym_hashes;
00823   struct elf_link_hash_entry ** sym_hashes_end;
00824   const Elf_Internal_Rela *     rel;
00825   const Elf_Internal_Rela *     rel_end;
00826 
00827   if (info->relocatable)
00828     return TRUE;
00829 
00830   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
00831   sym_hashes = elf_sym_hashes (abfd);
00832   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
00833   if (!elf_bad_symtab (abfd))
00834     sym_hashes_end -= symtab_hdr->sh_info;
00835 
00836   rel_end = relocs + sec->reloc_count;
00837 
00838   for (rel = relocs; rel < rel_end; rel++)
00839     {
00840       struct elf_link_hash_entry * h;
00841       unsigned long r_symndx;
00842 
00843       r_symndx = ELF32_R_SYM (rel->r_info);
00844 
00845       if (r_symndx < symtab_hdr->sh_info)
00846         h = NULL;
00847       else
00848        {
00849          h = sym_hashes [r_symndx - symtab_hdr->sh_info];
00850          while (h->root.type == bfd_link_hash_indirect
00851                || h->root.type == bfd_link_hash_warning)
00852            h = (struct elf_link_hash_entry *) h->root.u.i.link;
00853        }
00854 
00855       switch (ELF32_R_TYPE (rel->r_info))
00856         {
00857         /* This relocation describes the C++ object vtable hierarchy.
00858            Reconstruct it for later use during GC.  */
00859         case R_M68HC11_GNU_VTINHERIT:
00860           if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
00861             return FALSE;
00862           break;
00863 
00864         /* This relocation describes which C++ vtable entries are actually
00865            used.  Record for later use during GC.  */
00866         case R_M68HC11_GNU_VTENTRY:
00867           if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
00868             return FALSE;
00869           break;
00870         }
00871     }
00872 
00873   return TRUE;
00874 }
00875 
00876 /* Relocate a 68hc11/68hc12 ELF section.  */
00877 bfd_boolean
00878 elf32_m68hc11_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
00879                                 struct bfd_link_info *info,
00880                                 bfd *input_bfd, asection *input_section,
00881                                 bfd_byte *contents, Elf_Internal_Rela *relocs,
00882                                 Elf_Internal_Sym *local_syms,
00883                                 asection **local_sections)
00884 {
00885   Elf_Internal_Shdr *symtab_hdr;
00886   struct elf_link_hash_entry **sym_hashes;
00887   Elf_Internal_Rela *rel, *relend;
00888   const char *name = NULL;
00889   struct m68hc11_page_info *pinfo;
00890   const struct elf_backend_data * const ebd = get_elf_backend_data (input_bfd);
00891 
00892   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
00893   sym_hashes = elf_sym_hashes (input_bfd);
00894 
00895   /* Get memory bank parameters.  */
00896   m68hc11_elf_get_bank_parameters (info);
00897   pinfo = &m68hc11_elf_hash_table (info)->pinfo;
00898 
00899   rel = relocs;
00900   relend = relocs + input_section->reloc_count;
00901   for (; rel < relend; rel++)
00902     {
00903       int r_type;
00904       arelent arel;
00905       reloc_howto_type *howto;
00906       unsigned long r_symndx;
00907       Elf_Internal_Sym *sym;
00908       asection *sec;
00909       bfd_vma relocation = 0;
00910       bfd_reloc_status_type r = bfd_reloc_undefined;
00911       bfd_vma phys_page;
00912       bfd_vma phys_addr;
00913       bfd_vma insn_addr;
00914       bfd_vma insn_page;
00915       bfd_boolean is_far = FALSE;
00916       struct elf_link_hash_entry *h;
00917       const char* stub_name = 0;
00918 
00919       r_symndx = ELF32_R_SYM (rel->r_info);
00920       r_type = ELF32_R_TYPE (rel->r_info);
00921 
00922       if (r_type == R_M68HC11_GNU_VTENTRY
00923           || r_type == R_M68HC11_GNU_VTINHERIT )
00924         continue;
00925 
00926       (*ebd->elf_info_to_howto_rel) (input_bfd, &arel, rel);
00927       howto = arel.howto;
00928 
00929       h = NULL;
00930       sym = NULL;
00931       sec = NULL;
00932       if (r_symndx < symtab_hdr->sh_info)
00933        {
00934          sym = local_syms + r_symndx;
00935          sec = local_sections[r_symndx];
00936          relocation = (sec->output_section->vma
00937                      + sec->output_offset
00938                      + sym->st_value);
00939          is_far = (sym && (sym->st_other & STO_M68HC12_FAR));
00940          if (is_far)
00941            stub_name = (bfd_elf_string_from_elf_section
00942                       (input_bfd, symtab_hdr->sh_link,
00943                        sym->st_name));
00944        }
00945       else
00946        {
00947          bfd_boolean unresolved_reloc, warned;
00948 
00949          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
00950                                r_symndx, symtab_hdr, sym_hashes,
00951                                h, sec, relocation, unresolved_reloc,
00952                                warned);
00953 
00954          is_far = (h && (h->other & STO_M68HC12_FAR));
00955          stub_name = h->root.root.string;
00956        }
00957 
00958       if (sec != NULL && elf_discarded_section (sec))
00959        {
00960          /* For relocs against symbols from removed linkonce sections,
00961             or sections discarded by a linker script, we just want the
00962             section contents zeroed.  Avoid any special processing.  */
00963          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
00964          rel->r_info = 0;
00965          rel->r_addend = 0;
00966          continue;
00967        }
00968 
00969       if (info->relocatable)
00970        {
00971          /* This is a relocatable link.  We don't have to change
00972             anything, unless the reloc is against a section symbol,
00973             in which case we have to adjust according to where the
00974             section symbol winds up in the output section.  */
00975          if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
00976            rel->r_addend += sec->output_offset;
00977          continue;
00978        }
00979 
00980       if (h != NULL)
00981        name = h->root.root.string;
00982       else
00983        {
00984          name = (bfd_elf_string_from_elf_section
00985                 (input_bfd, symtab_hdr->sh_link, sym->st_name));
00986          if (name == NULL || *name == '\0')
00987            name = bfd_section_name (input_bfd, sec);
00988        }
00989 
00990       if (is_far && ELF32_R_TYPE (rel->r_info) == R_M68HC11_16)
00991        {
00992          struct elf32_m68hc11_stub_hash_entry* stub;
00993          struct m68hc11_elf_link_hash_table *htab;
00994 
00995          htab = m68hc11_elf_hash_table (info);
00996          stub = m68hc12_stub_hash_lookup (htab->stub_hash_table,
00997                                       name, FALSE, FALSE);
00998          if (stub)
00999            {
01000              relocation = stub->stub_offset
01001               + stub->stub_sec->output_section->vma
01002               + stub->stub_sec->output_offset;
01003              is_far = FALSE;
01004            }
01005        }
01006 
01007       /* Do the memory bank mapping.  */
01008       phys_addr = m68hc11_phys_addr (pinfo, relocation + rel->r_addend);
01009       phys_page = m68hc11_phys_page (pinfo, relocation + rel->r_addend);
01010       switch (r_type)
01011         {
01012         case R_M68HC11_24:
01013           /* Reloc used by 68HC12 call instruction.  */
01014           bfd_put_16 (input_bfd, phys_addr,
01015                       (bfd_byte*) contents + rel->r_offset);
01016           bfd_put_8 (input_bfd, phys_page,
01017                      (bfd_byte*) contents + rel->r_offset + 2);
01018           r = bfd_reloc_ok;
01019           r_type = R_M68HC11_NONE;
01020           break;
01021 
01022         case R_M68HC11_NONE:
01023           r = bfd_reloc_ok;
01024           break;
01025 
01026         case R_M68HC11_LO16:
01027           /* Reloc generated by %addr(expr) gas to obtain the
01028              address as mapped in the memory bank window.  */
01029           relocation = phys_addr;
01030           break;
01031 
01032         case R_M68HC11_PAGE:
01033           /* Reloc generated by %page(expr) gas to obtain the
01034              page number associated with the address.  */
01035           relocation = phys_page;
01036           break;
01037 
01038         case R_M68HC11_16:
01039           /* Get virtual address of instruction having the relocation.  */
01040           if (is_far)
01041             {
01042               const char* msg;
01043               char* buf;
01044               msg = _("Reference to the far symbol `%s' using a wrong "
01045                       "relocation may result in incorrect execution");
01046               buf = alloca (strlen (msg) + strlen (name) + 10);
01047               sprintf (buf, msg, name);
01048               
01049               (* info->callbacks->warning)
01050                 (info, buf, name, input_bfd, NULL, rel->r_offset);
01051             }
01052 
01053           /* Get virtual address of instruction having the relocation.  */
01054           insn_addr = input_section->output_section->vma
01055             + input_section->output_offset
01056             + rel->r_offset;
01057 
01058           insn_page = m68hc11_phys_page (pinfo, insn_addr);
01059 
01060           if (m68hc11_addr_is_banked (pinfo, relocation + rel->r_addend)
01061               && m68hc11_addr_is_banked (pinfo, insn_addr)
01062               && phys_page != insn_page)
01063             {
01064               const char* msg;
01065               char* buf;
01066 
01067               msg = _("banked address [%lx:%04lx] (%lx) is not in the same bank "
01068                       "as current banked address [%lx:%04lx] (%lx)");
01069 
01070               buf = alloca (strlen (msg) + 128);
01071               sprintf (buf, msg, phys_page, phys_addr,
01072                        (long) (relocation + rel->r_addend),
01073                        insn_page, m68hc11_phys_addr (pinfo, insn_addr),
01074                        (long) (insn_addr));
01075               if (!((*info->callbacks->warning)
01076                     (info, buf, name, input_bfd, input_section,
01077                      rel->r_offset)))
01078                 return FALSE;
01079               break;
01080             }
01081           if (phys_page != 0 && insn_page == 0)
01082             {
01083               const char* msg;
01084               char* buf;
01085 
01086               msg = _("reference to a banked address [%lx:%04lx] in the "
01087                       "normal address space at %04lx");
01088 
01089               buf = alloca (strlen (msg) + 128);
01090               sprintf (buf, msg, phys_page, phys_addr, insn_addr);
01091               if (!((*info->callbacks->warning)
01092                     (info, buf, name, input_bfd, input_section,
01093                      insn_addr)))
01094                 return FALSE;
01095 
01096               relocation = phys_addr;
01097               break;
01098             }
01099 
01100           /* If this is a banked address use the phys_addr so that
01101              we stay in the banked window.  */
01102           if (m68hc11_addr_is_banked (pinfo, relocation + rel->r_addend))
01103             relocation = phys_addr;
01104           break;
01105         }
01106       if (r_type != R_M68HC11_NONE)
01107         r = _bfd_final_link_relocate (howto, input_bfd, input_section,
01108                                       contents, rel->r_offset,
01109                                       relocation, rel->r_addend);
01110 
01111       if (r != bfd_reloc_ok)
01112        {
01113          const char * msg = (const char *) 0;
01114 
01115          switch (r)
01116            {
01117            case bfd_reloc_overflow:
01118              if (!((*info->callbacks->reloc_overflow)
01119                   (info, NULL, name, howto->name, (bfd_vma) 0,
01120                    input_bfd, input_section, rel->r_offset)))
01121               return FALSE;
01122              break;
01123 
01124            case bfd_reloc_undefined:
01125              if (!((*info->callbacks->undefined_symbol)
01126                   (info, name, input_bfd, input_section,
01127                    rel->r_offset, TRUE)))
01128               return FALSE;
01129              break;
01130 
01131            case bfd_reloc_outofrange:
01132              msg = _ ("internal error: out of range error");
01133              goto common_error;
01134 
01135            case bfd_reloc_notsupported:
01136              msg = _ ("internal error: unsupported relocation error");
01137              goto common_error;
01138 
01139            case bfd_reloc_dangerous:
01140              msg = _ ("internal error: dangerous error");
01141              goto common_error;
01142 
01143            default:
01144              msg = _ ("internal error: unknown error");
01145              /* fall through */
01146 
01147            common_error:
01148              if (!((*info->callbacks->warning)
01149                   (info, msg, name, input_bfd, input_section,
01150                    rel->r_offset)))
01151               return FALSE;
01152              break;
01153            }
01154        }
01155     }
01156 
01157   return TRUE;
01158 }
01159 
01160 
01161 
01162 /* Set and control ELF flags in ELF header.  */
01163 
01164 bfd_boolean
01165 _bfd_m68hc11_elf_set_private_flags (bfd *abfd, flagword flags)
01166 {
01167   BFD_ASSERT (!elf_flags_init (abfd)
01168              || elf_elfheader (abfd)->e_flags == flags);
01169 
01170   elf_elfheader (abfd)->e_flags = flags;
01171   elf_flags_init (abfd) = TRUE;
01172   return TRUE;
01173 }
01174 
01175 /* Merge backend specific data from an object file to the output
01176    object file when linking.  */
01177 
01178 bfd_boolean
01179 _bfd_m68hc11_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
01180 {
01181   flagword old_flags;
01182   flagword new_flags;
01183   bfd_boolean ok = TRUE;
01184 
01185   /* Check if we have the same endianess */
01186   if (!_bfd_generic_verify_endian_match (ibfd, obfd))
01187     return FALSE;
01188 
01189   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
01190       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
01191     return TRUE;
01192 
01193   new_flags = elf_elfheader (ibfd)->e_flags;
01194   elf_elfheader (obfd)->e_flags |= new_flags & EF_M68HC11_ABI;
01195   old_flags = elf_elfheader (obfd)->e_flags;
01196 
01197   if (! elf_flags_init (obfd))
01198     {
01199       elf_flags_init (obfd) = TRUE;
01200       elf_elfheader (obfd)->e_flags = new_flags;
01201       elf_elfheader (obfd)->e_ident[EI_CLASS]
01202        = elf_elfheader (ibfd)->e_ident[EI_CLASS];
01203 
01204       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
01205          && bfd_get_arch_info (obfd)->the_default)
01206        {
01207          if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
01208                                bfd_get_mach (ibfd)))
01209            return FALSE;
01210        }
01211 
01212       return TRUE;
01213     }
01214 
01215   /* Check ABI compatibility.  */
01216   if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
01217     {
01218       (*_bfd_error_handler)
01219        (_("%B: linking files compiled for 16-bit integers (-mshort) "
01220            "and others for 32-bit integers"), ibfd);
01221       ok = FALSE;
01222     }
01223   if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
01224     {
01225       (*_bfd_error_handler)
01226        (_("%B: linking files compiled for 32-bit double (-fshort-double) "
01227            "and others for 64-bit double"), ibfd);
01228       ok = FALSE;
01229     }
01230 
01231   /* Processor compatibility.  */
01232   if (!EF_M68HC11_CAN_MERGE_MACH (new_flags, old_flags))
01233     {
01234       (*_bfd_error_handler)
01235        (_("%B: linking files compiled for HCS12 with "
01236            "others compiled for HC12"), ibfd);
01237       ok = FALSE;
01238     }
01239   new_flags = ((new_flags & ~EF_M68HC11_MACH_MASK)
01240                | (EF_M68HC11_MERGE_MACH (new_flags, old_flags)));
01241 
01242   elf_elfheader (obfd)->e_flags = new_flags;
01243 
01244   new_flags &= ~(EF_M68HC11_ABI | EF_M68HC11_MACH_MASK);
01245   old_flags &= ~(EF_M68HC11_ABI | EF_M68HC11_MACH_MASK);
01246 
01247   /* Warn about any other mismatches */
01248   if (new_flags != old_flags)
01249     {
01250       (*_bfd_error_handler)
01251        (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
01252         ibfd, (unsigned long) new_flags, (unsigned long) old_flags);
01253       ok = FALSE;
01254     }
01255 
01256   if (! ok)
01257     {
01258       bfd_set_error (bfd_error_bad_value);
01259       return FALSE;
01260     }
01261 
01262   return TRUE;
01263 }
01264 
01265 bfd_boolean
01266 _bfd_m68hc11_elf_print_private_bfd_data (bfd *abfd, void *ptr)
01267 {
01268   FILE *file = (FILE *) ptr;
01269 
01270   BFD_ASSERT (abfd != NULL && ptr != NULL);
01271 
01272   /* Print normal ELF private data.  */
01273   _bfd_elf_print_private_bfd_data (abfd, ptr);
01274 
01275   /* xgettext:c-format */
01276   fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
01277 
01278   if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
01279     fprintf (file, _("[abi=32-bit int, "));
01280   else
01281     fprintf (file, _("[abi=16-bit int, "));
01282 
01283   if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
01284     fprintf (file, _("64-bit double, "));
01285   else
01286     fprintf (file, _("32-bit double, "));
01287 
01288   if (strcmp (bfd_get_target (abfd), "elf32-m68hc11") == 0)
01289     fprintf (file, _("cpu=HC11]"));
01290   else if (elf_elfheader (abfd)->e_flags & EF_M68HCS12_MACH)
01291     fprintf (file, _("cpu=HCS12]"));
01292   else
01293     fprintf (file, _("cpu=HC12]"));    
01294 
01295   if (elf_elfheader (abfd)->e_flags & E_M68HC12_BANKS)
01296     fprintf (file, _(" [memory=bank-model]"));
01297   else
01298     fprintf (file, _(" [memory=flat]"));
01299 
01300   fputc ('\n', file);
01301 
01302   return TRUE;
01303 }
01304 
01305 static void scan_sections_for_abi (bfd *abfd ATTRIBUTE_UNUSED,
01306                                    asection *asect, void *arg)
01307 {
01308   struct m68hc11_scan_param* p = (struct m68hc11_scan_param*) arg;
01309 
01310   if (asect->vma >= p->pinfo->bank_virtual)
01311     p->use_memory_banks = TRUE;
01312 }
01313   
01314 /* Tweak the OSABI field of the elf header.  */
01315 
01316 void
01317 elf32_m68hc11_post_process_headers (bfd *abfd, struct bfd_link_info *link_info)
01318 {
01319   struct m68hc11_scan_param param;
01320 
01321   if (link_info == 0)
01322     return;
01323 
01324   m68hc11_elf_get_bank_parameters (link_info);
01325 
01326   param.use_memory_banks = FALSE;
01327   param.pinfo = &m68hc11_elf_hash_table (link_info)->pinfo;
01328   bfd_map_over_sections (abfd, scan_sections_for_abi, &param);
01329   if (param.use_memory_banks)
01330     {
01331       Elf_Internal_Ehdr * i_ehdrp;
01332 
01333       i_ehdrp = elf_elfheader (abfd);
01334       i_ehdrp->e_flags |= E_M68HC12_BANKS;
01335     }
01336 }
01337