From 7a2f2d82fd0e757dfd6eb79637cb790959f52295 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Tue, 27 May 2014 17:14:49 -0400 Subject: [PATCH] Add new link-map-text hook and RX auto-vector support. * bfd/elf32-rx.c (get_symbol_value_maybe): New. (rx_elf_relocate_section): If we find a reloc against $tableentry$default$, redirect it to the appropriate $tableentry$$. (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. --- bfd/ChangeLog | 16 ++ bfd/elf32-rx.c | 397 +++++++++++++++++++++++++++++++++++++++ bfd/elf32-rx.h | 21 +++ ld/ChangeLog | 24 +++ ld/emultempl/aix.em | 3 +- ld/emultempl/armcoff.em | 3 +- ld/emultempl/beos.em | 3 +- ld/emultempl/elf32.em | 3 +- ld/emultempl/generic.em | 1 + ld/emultempl/gld960.em | 3 +- ld/emultempl/gld960c.em | 3 +- ld/emultempl/linux.em | 3 +- ld/emultempl/lnk960.em | 3 +- ld/emultempl/m68kcoff.em | 3 +- ld/emultempl/pe.em | 3 +- ld/emultempl/pep.em | 3 +- ld/emultempl/rxelf.em | 4 + ld/emultempl/sunos.em | 3 +- ld/emultempl/ticoff.em | 3 +- ld/emultempl/vanilla.em | 3 +- ld/ldemul.c | 7 + ld/ldemul.h | 7 + ld/ldlang.c | 2 + 23 files changed, 507 insertions(+), 14 deletions(-) create mode 100644 bfd/elf32-rx.h diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c674220f614..41eeea0045c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,19 @@ +2014-05-27 DJ Delorie + + * bfd/elf32-rx.c (get_symbol_value_maybe): New. + (rx_elf_relocate_section): If we find a reloc against + $tableentry$default$, redirect it to the appropriate + $tableentry$$. + (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 * elf32-msp430.c (msp430_elf_relax_adjust_locals): Avoid overflow. diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c index 2045cb76bad..e1856a9591d 100644 --- a/bfd/elf32-rx.c +++ b/bfd/elf32-rx.c @@ -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$$ */ + 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); @@ -3543,6 +3647,298 @@ static const struct bfd_elf_special_section elf32_rx_special_sections[] = { STRING_COMMA_LEN (".preinit_array"), 0, SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_EXECINSTR }, { NULL, 0, 0, 0, 0 } }; + +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$. */ + 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; +} + + +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$. */ + 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); +} + #define ELF_ARCH bfd_arch_rx #define ELF_MACHINE_CODE EM_RX @@ -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 index 00000000000..377938838e4 --- /dev/null +++ b/bfd/elf32-rx.h @@ -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); diff --git a/ld/ChangeLog b/ld/ChangeLog index 4e1ab6cf013..a980c9affd3 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,27 @@ +2014-05-27 DJ Delorie + + * 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 * ldlang.c (base): Move variable to.. diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em index caa74a990e2..56985cfa753 100644 --- a/ld/emultempl/aix.em +++ b/ld/emultempl/aix.em @@ -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 diff --git a/ld/emultempl/armcoff.em b/ld/emultempl/armcoff.em index 8e9befcaa6e..de10a6c5fa6 100644 --- a/ld/emultempl/armcoff.em +++ b/ld/emultempl/armcoff.em @@ -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 diff --git a/ld/emultempl/beos.em b/ld/emultempl/beos.em index 2196510795f..732abfdcfa8 100644 --- a/ld/emultempl/beos.em +++ b/ld/emultempl/beos.em @@ -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 diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 31761ca2c2f..3ebf3b59077 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -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 diff --git a/ld/emultempl/generic.em b/ld/emultempl/generic.em index b22e2a672c1..aac4b93ef53 100644 --- a/ld/emultempl/generic.em +++ b/ld/emultempl/generic.em @@ -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 diff --git a/ld/emultempl/gld960.em b/ld/emultempl/gld960.em index 0df99e37765..5632f31a8d8 100644 --- a/ld/emultempl/gld960.em +++ b/ld/emultempl/gld960.em @@ -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 diff --git a/ld/emultempl/gld960c.em b/ld/emultempl/gld960c.em index 805e69bf2f4..dd69c7985e3 100644 --- a/ld/emultempl/gld960c.em +++ b/ld/emultempl/gld960c.em @@ -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 diff --git a/ld/emultempl/linux.em b/ld/emultempl/linux.em index b30e872c3e6..bbc5946df3c 100644 --- a/ld/emultempl/linux.em +++ b/ld/emultempl/linux.em @@ -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 diff --git a/ld/emultempl/lnk960.em b/ld/emultempl/lnk960.em index 9c6ff38dbfa..6364f6df383 100644 --- a/ld/emultempl/lnk960.em +++ b/ld/emultempl/lnk960.em @@ -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 diff --git a/ld/emultempl/m68kcoff.em b/ld/emultempl/m68kcoff.em index 1ea900a7569..e46889a0ff1 100644 --- a/ld/emultempl/m68kcoff.em +++ b/ld/emultempl/m68kcoff.em @@ -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 diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index ba51cc0488c..3a375083d08 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -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 diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index d1575e2673d..1f786556568 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -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 diff --git a/ld/emultempl/rxelf.em b/ld/emultempl/rxelf.em index 599879016e4..6386abd3bf9 100644 --- a/ld/emultempl/rxelf.em +++ b/ld/emultempl/rxelf.em @@ -25,6 +25,8 @@ test -z "$TARGET2_TYPE" && TARGET2_TYPE="rel" fragment <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); +} diff --git a/ld/ldemul.h b/ld/ldemul.h index a9ea2f60af7..27b13ad58b6 100644 --- a/ld/ldemul.h +++ b/ld/ldemul.h @@ -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 { diff --git a/ld/ldlang.c b/ld/ldlang.c index b48a9b37b51..585914fe387 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -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 -- 2.30.2