Add new link-map-text hook and RX auto-vector support.
authorDJ Delorie <dj@redhat.com>
Tue, 27 May 2014 21:14:49 +0000 (17:14 -0400)
committerDJ Delorie <dj@redhat.com>
Tue, 27 May 2014 21:14:49 +0000 (17:14 -0400)
* bfd/elf32-rx.c (get_symbol_value_maybe): New.
(rx_elf_relocate_section): If we find a reloc against
$tableentry$default$<name>, redirect it to the appropriate
$tableentry$<n>$.
(RX_Table_Info): New.
(rx_table_find): New.  Check all tables and SEC_KEEP all sections
with table parts in them.
(rx_check_directives): New.
(rx_table_map_2): New.
(rx_table_map): New.
(rx_additional_link_map_text): New.  Called to dump tables to the
map file.
* bfd/elf32-rx.h: New.

* ld/ldemul.h (extra_map_file_text): New field.
(ldemul_extra_map_file_text): Declare.
* ld/ldemul.c (ldemul_extra_map_file_text): Define.
* ld/ldlang.c (lang_map): Call it.

* ld/emultempl/rxelf.em: Add extra_map_file_text hook.
* ld/emultempl/aix.em: Add NULL extra_map_file_text hook.
* ld/emultempl/armcoff.em: Likewise.
* ld/emultempl/beos.em: Likewise.
* ld/emultempl/elf32.em: Likewise.
* ld/emultempl/generic.em: Likewise.
* ld/emultempl/gld960.em: Likewise.
* ld/emultempl/gld960c.em: Likewise.
* ld/emultempl/linux.em: Likewise.
* ld/emultempl/lnk960.em: Likewise.
* ld/emultempl/m68kcoff.em: Likewise.
* ld/emultempl/pe.em: Likewise.
* ld/emultempl/pep.em: Likewise.
* ld/emultempl/sunos.em: Likewise.
* ld/emultempl/ticoff.em: Likewise.
* ld/emultempl/vanilla.em: Likewise.

23 files changed:
bfd/ChangeLog
bfd/elf32-rx.c
bfd/elf32-rx.h [new file with mode: 0644]
ld/ChangeLog
ld/emultempl/aix.em
ld/emultempl/armcoff.em
ld/emultempl/beos.em
ld/emultempl/elf32.em
ld/emultempl/generic.em
ld/emultempl/gld960.em
ld/emultempl/gld960c.em
ld/emultempl/linux.em
ld/emultempl/lnk960.em
ld/emultempl/m68kcoff.em
ld/emultempl/pe.em
ld/emultempl/pep.em
ld/emultempl/rxelf.em
ld/emultempl/sunos.em
ld/emultempl/ticoff.em
ld/emultempl/vanilla.em
ld/ldemul.c
ld/ldemul.h
ld/ldlang.c

index c674220..41eeea0 100644 (file)
@@ -1,3 +1,19 @@
+2014-05-27  DJ Delorie  <dj@redhat.com>
+
+       * bfd/elf32-rx.c (get_symbol_value_maybe): New.
+       (rx_elf_relocate_section): If we find a reloc against
+       $tableentry$default$<name>, redirect it to the appropriate
+       $tableentry$<n>$.
+       (RX_Table_Info): New.
+       (rx_table_find): New.  Check all tables and SEC_KEEP all sections
+       with table parts in them.
+       (rx_check_directives): New.
+       (rx_table_map_2): New.
+       (rx_table_map): New.
+       (rx_additional_link_map_text): New.  Called to dump tables to the
+       map file.
+       * bfd/elf32-rx.h: New.
+
 2014-05-20  DJ Delorie  <dj@redhat.com>
 
        * elf32-msp430.c (msp430_elf_relax_adjust_locals): Avoid overflow.
index 2045cb7..e1856a9 100644 (file)
@@ -24,6 +24,7 @@
 #include "elf-bfd.h"
 #include "elf/rx.h"
 #include "libiberty.h"
+#include "elf32-rx.h"
 
 #define RX_OPCODE_BIG_ENDIAN 0
 
@@ -335,6 +336,26 @@ get_symbol_value (const char *            name,
 
   return value;
 }
+static bfd_vma
+get_symbol_value_maybe (const char *            name,
+                       struct bfd_link_info *  info)
+{
+  bfd_vma value = 0;
+  struct bfd_link_hash_entry * h;
+
+  h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
+
+  if (h == NULL
+      || (h->type != bfd_link_hash_defined
+         && h->type != bfd_link_hash_defweak))
+    return 0;
+  else
+    value = (h->u.def.value
+            + h->u.def.section->output_section->vma
+            + h->u.def.section->output_offset);
+
+  return value;
+}
 
 static bfd_vma
 get_gp (bfd_reloc_status_type * status,
@@ -464,6 +485,9 @@ rx_elf_relocate_section
   Elf_Internal_Rela *           relend;
   bfd_boolean                  pid_mode;
   bfd_boolean                  saw_subtract = FALSE;
+  const char *                 table_default_cache = NULL;
+  bfd_vma                      table_start_cache = 0;
+  bfd_vma                      table_end_cache = 0;
 
   if (elf_elfheader (output_bfd)->e_flags & E_FLAG_RX_PID)
     pid_mode = TRUE;
@@ -520,6 +544,86 @@ rx_elf_relocate_section
          name = h->root.root.string;
        }
 
+      if (strncmp (name, "$tableentry$default$", 20) == 0)
+       {
+         bfd_vma entry_vma;
+         int idx;
+         char *buf;
+         bfd_reloc_status_type tstat = 0;
+
+         if (table_default_cache != name)
+           {
+
+             /* All relocs for a given table should be to the same
+                (weak) default symbol) so we can use it to detect a
+                cache miss.  We use the offset into the table to find
+                the "real" symbol.  Calculate and store the table's
+                offset here.  */
+
+             table_default_cache = name;
+
+             /* We have already done error checking in rx_table_find().  */
+
+             buf = (char *) malloc (13 + strlen (name + 20));
+
+             sprintf (buf, "$tablestart$%s", name + 20);
+             tstat = 0;
+             table_start_cache = get_symbol_value (buf,
+                                                   &tstat,
+                                                   info,
+                                                   input_bfd,
+                                                   input_section,
+                                                   rel->r_offset);
+
+             sprintf (buf, "$tableend$%s", name + 20);
+             tstat = 0;
+             table_end_cache = get_symbol_value (buf,
+                                                 &tstat,
+                                                 info,
+                                                 input_bfd,
+                                                 input_section,
+                                                 rel->r_offset);
+
+             free (buf);
+           }
+
+         entry_vma = (input_section->output_section->vma
+                      + input_section->output_offset
+                      + rel->r_offset);
+
+         if (table_end_cache <= entry_vma || entry_vma < table_start_cache)
+           {
+             _bfd_error_handler (_("%B:%A: table entry %s outside table"),
+                                 input_bfd, input_section,
+                                 name);
+           }
+         else if ((int) (entry_vma - table_start_cache) % 4)
+           {
+             _bfd_error_handler (_("%B:%A: table entry %s not word-aligned within table"),
+                                 input_bfd, input_section,
+                                 name);
+           }
+         else
+           {
+             idx = (int) (entry_vma - table_start_cache) / 4;
+
+             /* This will look like $tableentry$<N>$<name> */
+             buf = (char *) malloc (12 + 20 + strlen (name + 20));
+             sprintf (buf, "$tableentry$%d$%s", idx, name + 20);
+
+             h = (struct elf_link_hash_entry *) bfd_link_hash_lookup (info->hash, buf, FALSE, FALSE, TRUE);
+
+             if (h)
+               {
+                 relocation = (h->root.u.def.value
+                               + h->root.u.def.section->output_section->vma
+                               + h->root.u.def.section->output_offset);;
+               }
+
+             free (buf);
+           }
+       }
+
       if (sec != NULL && discarded_section (sec))
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
                                         rel, 1, relend, howto, 0, contents);
@@ -3544,6 +3648,298 @@ static const struct bfd_elf_special_section elf32_rx_special_sections[] =
   { NULL,                        0,      0, 0,            0 }
 };
 \f
+typedef struct {
+  bfd *abfd;
+  struct bfd_link_info *info;
+  bfd_vma table_start;
+  int table_size;
+  bfd_vma *table_handlers;
+  bfd_vma table_default_handler;
+  struct bfd_link_hash_entry **table_entries;
+  struct bfd_link_hash_entry *table_default_entry;
+  FILE *mapfile;
+} RX_Table_Info;
+
+static bfd_boolean
+rx_table_find (struct bfd_hash_entry *vent, void *vinfo)
+{
+  RX_Table_Info *info = (RX_Table_Info *)vinfo;
+  struct bfd_link_hash_entry *ent = (struct bfd_link_hash_entry *)vent;
+  const char *name; /* of the symbol we've found */
+  asection *sec;
+  struct bfd *abfd;
+  int idx;
+  const char *tname; /* name of the table */
+  bfd_vma start_addr, end_addr;
+  char *buf;
+  struct bfd_link_hash_entry * h;
+
+  /* We're looking for globally defined symbols of the form
+     $tablestart$<NAME>.  */
+  if (ent->type != bfd_link_hash_defined
+      && ent->type != bfd_link_hash_defweak)
+    return TRUE;
+
+  name = ent->root.string;
+  sec = ent->u.def.section;
+  abfd = sec->owner;
+
+  if (strncmp (name, "$tablestart$", 12))
+    return TRUE;
+
+  sec->flags |= SEC_KEEP;
+
+  tname = name + 12;
+
+  start_addr = ent->u.def.value;
+
+  /* At this point, we can't build the table but we can (and must)
+     find all the related symbols and mark their sections as SEC_KEEP
+     so we don't garbage collect them.  */
+
+  buf = (char *) malloc (12 + 10 + strlen (tname));
+
+  sprintf (buf, "$tableend$%s", tname);
+  h = bfd_link_hash_lookup (info->info->hash, buf, FALSE, FALSE, TRUE);
+  if (!h || (h->type != bfd_link_hash_defined
+            && h->type != bfd_link_hash_defweak))
+    {
+      _bfd_error_handler (_("%B:%A: table %s missing corresponding %s"),
+                         abfd, sec, name, buf);
+      return TRUE;
+    }
+
+  if (h->u.def.section != ent->u.def.section)
+    {
+      _bfd_error_handler (_("%B:%A: %s and %s must be in the same input section"),
+                         h->u.def.section->owner, h->u.def.section,
+                         name, buf);
+      return TRUE;
+    }
+
+  end_addr = h->u.def.value;
+
+  sprintf (buf, "$tableentry$default$%s", tname);
+  h = bfd_link_hash_lookup (info->info->hash, buf, FALSE, FALSE, TRUE);
+  if (h && (h->type == bfd_link_hash_defined
+           || h->type == bfd_link_hash_defweak))
+    {
+      h->u.def.section->flags |= SEC_KEEP;
+    }
+
+  for (idx = 0; idx < (int) (end_addr - start_addr) / 4; idx ++)
+    {
+      sprintf (buf, "$tableentry$%d$%s", idx, tname);
+      h = bfd_link_hash_lookup (info->info->hash, buf, FALSE, FALSE, TRUE);
+      if (h && (h->type == bfd_link_hash_defined
+               || h->type == bfd_link_hash_defweak))
+       {
+         h->u.def.section->flags |= SEC_KEEP;
+       }
+    }
+
+  /* Return TRUE to keep scanning, FALSE to end the traversal.  */
+  return TRUE;
+}
+
+/* We need to check for table entry symbols and build the tables, and
+   we need to do it before the linker does garbage collection.  This function is
+   called once per input object file.  */
+static bfd_boolean
+rx_check_directives
+    (bfd *                     abfd ATTRIBUTE_UNUSED,
+     struct bfd_link_info *    info ATTRIBUTE_UNUSED)
+{
+  RX_Table_Info stuff;
+
+  stuff.abfd = abfd;
+  stuff.info = info;
+  bfd_hash_traverse (&(info->hash->table), rx_table_find, &stuff);
+
+  return TRUE;
+}
+
+\f
+static bfd_boolean
+rx_table_map_2 (struct bfd_hash_entry *vent, void *vinfo)
+{
+  RX_Table_Info *info = (RX_Table_Info *)vinfo;
+  struct bfd_link_hash_entry *ent = (struct bfd_link_hash_entry *)vent;
+  int idx;
+  const char *name;
+  bfd_vma addr;
+
+  /* See if the symbol ENT has an address listed in the table, and
+     isn't a debug/special symbol.  If so, put it in the table.  */
+
+  if (ent->type != bfd_link_hash_defined
+      && ent->type != bfd_link_hash_defweak)
+    return TRUE;
+
+  name = ent->root.string;
+
+  if (name[0] == '$' || name[0] == '.' || name[0] < ' ')
+    return TRUE;
+
+  addr = (ent->u.def.value
+         + ent->u.def.section->output_section->vma
+         + ent->u.def.section->output_offset);
+
+  for (idx = 0; idx < info->table_size; idx ++)
+    if (addr == info->table_handlers[idx])
+      info->table_entries[idx] = ent;
+
+  if (addr == info->table_default_handler)
+    info->table_default_entry = ent;
+
+  return TRUE;
+}
+
+static bfd_boolean
+rx_table_map (struct bfd_hash_entry *vent, void *vinfo)
+{
+  RX_Table_Info *info = (RX_Table_Info *)vinfo;
+  struct bfd_link_hash_entry *ent = (struct bfd_link_hash_entry *)vent;
+  const char *name; /* of the symbol we've found */
+  asection *sec;
+  struct bfd *abfd;
+  int idx;
+  const char *tname; /* name of the table */
+  bfd_vma start_addr, end_addr;
+  char *buf;
+  struct bfd_link_hash_entry * h;
+  int need_elipses;
+
+  /* We're looking for globally defined symbols of the form
+     $tablestart$<NAME>.  */
+  if (ent->type != bfd_link_hash_defined
+      && ent->type != bfd_link_hash_defweak)
+    return TRUE;
+
+  name = ent->root.string;
+  sec = ent->u.def.section;
+  abfd = sec->owner;
+
+  if (strncmp (name, "$tablestart$", 12))
+    return TRUE;
+
+  tname = name + 12;
+  start_addr = (ent->u.def.value
+               + ent->u.def.section->output_section->vma
+               + ent->u.def.section->output_offset);
+
+  buf = (char *) malloc (12 + 10 + strlen (tname));
+
+  sprintf (buf, "$tableend$%s", tname);
+  end_addr = get_symbol_value_maybe (buf, info->info);
+
+  sprintf (buf, "$tableentry$default$%s", tname);
+  h = bfd_link_hash_lookup (info->info->hash, buf, FALSE, FALSE, TRUE);
+  if (h)
+    {
+      info->table_default_handler = (h->u.def.value
+                                    + h->u.def.section->output_section->vma
+                                    + h->u.def.section->output_offset);
+    }
+  else
+    /* Zero is a valid handler address!  */
+    info->table_default_handler = (bfd_vma) (-1);
+  info->table_default_entry = NULL;
+
+  info->table_start = start_addr;
+  info->table_size = (int) (end_addr - start_addr) / 4;
+  info->table_handlers = (bfd_vma *) malloc (info->table_size * sizeof (bfd_vma));
+  info->table_entries = (struct bfd_link_hash_entry **) malloc (info->table_size * sizeof (struct bfd_link_hash_entry));
+
+  for (idx = 0; idx < (int) (end_addr - start_addr) / 4; idx ++)
+    {
+      sprintf (buf, "$tableentry$%d$%s", idx, tname);
+      h = bfd_link_hash_lookup (info->info->hash, buf, FALSE, FALSE, TRUE);
+      if (h && (h->type == bfd_link_hash_defined
+               || h->type == bfd_link_hash_defweak))
+       {
+         info->table_handlers[idx] = (h->u.def.value
+                                      + h->u.def.section->output_section->vma
+                                      + h->u.def.section->output_offset);
+       }
+      else
+       info->table_handlers[idx] = info->table_default_handler;
+      info->table_entries[idx] = NULL;
+    }
+
+  free (buf);
+
+  bfd_hash_traverse (&(info->info->hash->table), rx_table_map_2, info);
+
+  fprintf (info->mapfile, "\nRX Vector Table: %s has %d entries at 0x%08lx\n\n",
+          tname, info->table_size, start_addr);
+
+  if (info->table_default_entry)
+    fprintf (info->mapfile, "  default handler is: %s at 0x%08lx\n",
+            info->table_default_entry->root.string,
+            info->table_default_handler);
+  else if (info->table_default_handler != (bfd_vma)(-1))
+    fprintf (info->mapfile, "  default handler is at 0x%08lx\n",
+            info->table_default_handler);
+  else
+    fprintf (info->mapfile, "  no default handler\n");
+
+  need_elipses = 1;
+  for (idx = 0; idx < info->table_size; idx ++)
+    {
+      if (info->table_handlers[idx] == info->table_default_handler)
+       {
+         if (need_elipses)
+           fprintf (info->mapfile, "  . . .\n");
+         need_elipses = 0;
+         continue;
+       }
+      need_elipses = 1;
+
+      fprintf (info->mapfile, "  0x%08lx [%3d] ", start_addr + 4 * idx, idx);
+
+      if (info->table_handlers[idx] == (bfd_vma) (-1))
+       fprintf (info->mapfile, "(no handler found)\n");
+
+      else if (info->table_handlers[idx] == info->table_default_handler)
+       {
+         if (info->table_default_entry)
+           fprintf (info->mapfile, "(default)\n");
+         else
+           fprintf (info->mapfile, "(default)\n");
+       }
+
+      else if (info->table_entries[idx])
+       {
+         fprintf (info->mapfile, "0x%08lx %s\n", info->table_handlers[idx], info->table_entries[idx]->root.string);
+       }
+
+      else
+       {
+         fprintf (info->mapfile, "0x%08lx ???\n", info->table_handlers[idx]);
+       }
+    }
+  if (need_elipses)
+    fprintf (info->mapfile, "  . . .\n");
+
+  return TRUE;
+}
+
+void
+rx_additional_link_map_text (bfd *obfd, struct bfd_link_info *info, FILE *mapfile)
+{
+  /* We scan the symbol table looking for $tableentry$'s, and for
+     each, try to deduce which handlers go with which entries.  */
+
+  RX_Table_Info stuff;
+
+  stuff.abfd = obfd;
+  stuff.info = info;
+  stuff.mapfile = mapfile;
+  bfd_hash_traverse (&(info->hash->table), rx_table_map, &stuff);
+}
+
+\f
 #define ELF_ARCH               bfd_arch_rx
 #define ELF_MACHINE_CODE       EM_RX
 #define ELF_MAXPAGESIZE                0x1000
@@ -3572,6 +3968,7 @@ static const struct bfd_elf_special_section elf32_rx_special_sections[] =
 #define bfd_elf32_bfd_final_link               rx_final_link
 #define bfd_elf32_bfd_relax_section            elf32_rx_relax_section_wrapper
 #define elf_backend_special_sections           elf32_rx_special_sections
+#define elf_backend_check_directives           rx_check_directives
 
 #include "elf32-target.h"
 
diff --git a/bfd/elf32-rx.h b/bfd/elf32-rx.h
new file mode 100644 (file)
index 0000000..3779388
--- /dev/null
@@ -0,0 +1,21 @@
+/* Renesas RX specific support for 32-bit ELF.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+void rx_additional_link_map_text (bfd *obfd, struct bfd_link_info *info, FILE *mapfile);
index 4e1ab6c..a980c9a 100644 (file)
@@ -1,3 +1,27 @@
+2014-05-27  DJ Delorie  <dj@redhat.com>
+
+       * ld/ldemul.h (extra_map_file_text): New field.
+       (ldemul_extra_map_file_text): Declare.
+       * ld/ldemul.c (ldemul_extra_map_file_text): Define.
+       * ld/ldlang.c (lang_map): Call it.
+
+       * ld/emultempl/rxelf.em: Add extra_map_file_text hook.
+       * ld/emultempl/aix.em: Add NULL extra_map_file_text hook.
+       * ld/emultempl/armcoff.em: Likewise.
+       * ld/emultempl/beos.em: Likewise.
+       * ld/emultempl/elf32.em: Likewise.
+       * ld/emultempl/generic.em: Likewise.
+       * ld/emultempl/gld960.em: Likewise.
+       * ld/emultempl/gld960c.em: Likewise.
+       * ld/emultempl/linux.em: Likewise.
+       * ld/emultempl/lnk960.em: Likewise.
+       * ld/emultempl/m68kcoff.em: Likewise.
+       * ld/emultempl/pe.em: Likewise.
+       * ld/emultempl/pep.em: Likewise.
+       * ld/emultempl/sunos.em: Likewise.
+       * ld/emultempl/ticoff.em: Likewise.
+       * ld/emultempl/vanilla.em: Likewise.
+
 2014-05-24  Alan Modra  <amodra@gmail.com>
 
        * ldlang.c (base): Move variable to..
index caa74a9..56985cf 100644 (file)
@@ -1553,6 +1553,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
   NULL,                                /* list_options */
   NULL,                                /* recognized_file */
   NULL,                                /* find potential_libraries */
-  NULL                         /* new_vers_pattern */
+  NULL,                                /* new_vers_pattern */
+  NULL                         /* extra_map_file_text */
 };
 EOF
index 8e9befc..de10a6c 100644 (file)
@@ -279,6 +279,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld${EMULATION_NAME}_list_options,
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
-  NULL /* new_vers_pattern */
+  NULL,        /* new_vers_pattern */
+  NULL /* extra_map_file_text */
 };
 EOF
index 2196510..732abfd 100644 (file)
@@ -777,6 +777,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   NULL,        /* list options */
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
-  NULL /* new_vers_pattern */
+  NULL,        /* new_vers_pattern */
+  NULL /* extra_map_file_text */
 };
 EOF
index 31761ca..3ebf3b5 100644 (file)
@@ -2498,6 +2498,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
   ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
-  ${LDEMUL_NEW_VERS_PATTERN-NULL}
+  ${LDEMUL_NEW_VERS_PATTERN-NULL},
+  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
 };
 EOF
index b22e2a6..aac4b93 100644 (file)
@@ -156,5 +156,6 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_RECOGNIZED_FILE-NULL},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
   ${LDEMUL_NEW_VERS_PATTERN-NULL}
+  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
 };
 EOF
index 0df99e3..5632f31 100644 (file)
@@ -148,6 +148,7 @@ struct ld_emulation_xfer_struct ld_gld960_emulation =
   NULL,        /* list options */
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
-  NULL /* new_vers_pattern */
+  NULL,        /* new_vers_pattern */
+  NULL /* extra_map_file_text */
 };
 EOF
index 805e69b..dd69c79 100644 (file)
@@ -161,6 +161,7 @@ struct ld_emulation_xfer_struct ld_gld960coff_emulation =
   NULL,        /* list options */
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
-  NULL /* new_vers_pattern */
+  NULL,        /* new_vers_pattern */
+  NULL /* extra_map_file_text */
 };
 EOF
index b30e872..bbc5946 100644 (file)
@@ -205,6 +205,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   NULL,        /* list options */
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
-  NULL /* new_vers_pattern */
+  NULL,        /* new_vers_pattern */
+  NULL /* extra_map_file_text */
 };
 EOF
index 9c6ff38..6364f6d 100644 (file)
@@ -342,6 +342,7 @@ struct ld_emulation_xfer_struct ld_lnk960_emulation =
   NULL,        /* list options */
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
-  NULL /* new_vers_pattern */
+  NULL,        /* new_vers_pattern */
+  NULL /* extra_map_file_text */
 };
 EOF
index 1ea900a..e46889a 100644 (file)
@@ -239,6 +239,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   NULL,        /* list options */
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
-  NULL /* new_vers_pattern */
+  NULL,        /* new_vers_pattern */
+  NULL /* extra_map_file_text */
 };
 EOF
index ba51cc0..3a37508 100644 (file)
@@ -2449,6 +2449,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld_${EMULATION_NAME}_list_options,
   gld_${EMULATION_NAME}_recognized_file,
   gld_${EMULATION_NAME}_find_potential_libraries,
-  NULL /* new_vers_pattern.  */
+  NULL,        /* new_vers_pattern.  */
+  NULL /* extra_map_file_text.  */
 };
 EOF
index d1575e2..1f78655 100644 (file)
@@ -2213,6 +2213,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld_${EMULATION_NAME}_list_options,
   gld_${EMULATION_NAME}_recognized_file,
   gld_${EMULATION_NAME}_find_potential_libraries,
-  NULL /* new_vers_pattern.  */
+  NULL,        /* new_vers_pattern.  */
+  NULL /* extra_map_file_text */
 };
 EOF
index 5998790..6386abd 100644 (file)
@@ -25,6 +25,8 @@
 test -z "$TARGET2_TYPE" && TARGET2_TYPE="rel"
 fragment <<EOF
 
+#include "elf32-rx.h"
+
 static bfd_boolean no_flag_mismatch_warnings = TRUE;
 static bfd_boolean ignore_lma = TRUE;
 
@@ -86,3 +88,5 @@ PARSE_AND_LIST_ARGS_CASES='
 '
 
 LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=rx_elf_create_output_section_statements
+
+LDEMUL_EXTRA_MAP_FILE_TEXT=rx_additional_link_map_text
index b527bba..e57e1f0 100644 (file)
@@ -1033,6 +1033,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   NULL,        /* list options */
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
-  NULL /* new_vers_pattern */
+  NULL,        /* new_vers_pattern */
+  NULL /* extra_map_file_text */
 };
 EOF
index a94f937..c403d56 100644 (file)
@@ -180,6 +180,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld_${EMULATION_NAME}_list_options,
   NULL, /* recognized file */
   NULL,        /* find_potential_libraries */
-  NULL /* new_vers_pattern */
+  NULL,        /* new_vers_pattern */
+  NULL  /* extra_map_file_text */
 };
 EOF
index f53a4e3..f8ade99 100644 (file)
@@ -81,6 +81,7 @@ struct ld_emulation_xfer_struct ld_vanilla_emulation =
   NULL,        /* list options */
   NULL,        /* recognized file */
   NULL,        /* find_potential_libraries */
-  NULL /* new_vers_pattern */
+  NULL,        /* new_vers_pattern */
+  NULL /* extra_map_file_text */
 };
 EOF
index edbc9ee..6145c47 100644 (file)
@@ -348,3 +348,10 @@ ldemul_new_vers_pattern (struct bfd_elf_version_expr *entry)
     entry = (*ld_emulation->new_vers_pattern) (entry);
   return entry;
 }
+
+void
+ldemul_extra_map_file_text (bfd *abfd, struct bfd_link_info *info, FILE *mapf)
+{
+  if (ld_emulation->extra_map_file_text)
+    ld_emulation->extra_map_file_text (abfd, info, mapf);
+}
index a9ea2f6..27b13ad 100644 (file)
@@ -94,6 +94,8 @@ extern int  ldemul_find_potential_libraries
   (char *, struct lang_input_statement_struct *);
 extern struct bfd_elf_version_expr *ldemul_new_vers_pattern
   (struct bfd_elf_version_expr *);
+extern void ldemul_extra_map_file_text
+  (bfd *, struct bfd_link_info *, FILE *);
 
 typedef struct ld_emulation_xfer_struct {
   /* Run before parsing the command line and script file.
@@ -194,6 +196,11 @@ typedef struct ld_emulation_xfer_struct {
   struct bfd_elf_version_expr * (*new_vers_pattern)
     (struct bfd_elf_version_expr *);
 
+  /* Called when printing the map file, in case there are
+     emulation-specific sections for it.  */
+  void (*extra_map_file_text)
+    (bfd *, struct bfd_link_info *, FILE *);
+
 } ld_emulation_xfer_type;
 
 typedef enum {
index b48a9b3..585914f 100644 (file)
@@ -2120,6 +2120,8 @@ lang_map (void)
     }
   lang_statement_iteration++;
   print_statements ();
+
+  ldemul_extra_map_file_text (link_info.output_bfd, &link_info, config.map_file);
 }
 
 static bfd_boolean