From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16510 invoked by alias); 10 May 2014 02:33:24 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 16499 invoked by uid 89); 10 May 2014 02:33:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.0 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS,UNSUBSCRIBE_BODY autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 10 May 2014 02:33:20 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s4A2XFfo019829 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 9 May 2014 22:33:15 -0400 Received: from greed.delorie.com (ovpn-113-109.phx2.redhat.com [10.3.113.109]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s4A2XD72026305 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Fri, 9 May 2014 22:33:14 -0400 Received: from greed.delorie.com (greed.delorie.com [127.0.0.1]) by greed.delorie.com (8.14.4/8.14.4) with ESMTP id s4A2XCDT030017; Fri, 9 May 2014 22:33:12 -0400 Received: (from dj@localhost) by greed.delorie.com (8.14.4/8.14.4/Submit) id s4A2XCOR030016; Fri, 9 May 2014 22:33:12 -0400 Date: Sat, 10 May 2014 02:33:00 -0000 Message-Id: <201405100233.s4A2XCOR030016@greed.delorie.com> From: DJ Delorie To: Alan Modra CC: gingold@adacore.com, binutils@sourceware.org In-reply-to: <20140507030239.GY16139@bubble.grove.modra.org> (message from Alan Modra on Wed, 7 May 2014 12:32:39 +0930) Subject: Re: [rfc] new bfd hook: additional link map text References: <201404110214.s3B2E2IQ016910@greed.delorie.com> <15F27C34-BFCC-4A1D-A705-C3AEB0464BF2@adacore.com> <201404222055.s3MKt75Y011634@greed.delorie.com> <201405061515.s46FFnQk025221@greed.delorie.com> <20140507030239.GY16139@bubble.grove.modra.org> X-IsSubscribed: yes X-SW-Source: 2014-05/txt/msg00093.txt.bz2 Here's the current patch, without the debugs, with elf32-rx.h, and without the old bfd hook. In case you're wondering, the purpose for all this is to have better support for auto-generated interrupt vector tables. The compiler sets up all the hooks, the bfd pass stitches the tables together, and this new linker map hook dumps the generated table info to the map file. * 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. diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c index 2045cb7..e1856a9 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); @@ -3544,6 +3648,298 @@ static const struct bfd_elf_special_section elf32_rx_special_sections[] = { 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 #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 index 0000000..3779388 --- /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/emultempl/aix.em b/ld/emultempl/aix.em index caa74a9..56985cf 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 8e9befc..de10a6c 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 2196510..732abfd 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 31761ca..3ebf3b5 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 b22e2a6..aac4b93 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 0df99e3..5632f31 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 805e69b..dd69c79 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 b30e872..bbc5946 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 9c6ff38..6364f6d 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 1ea900a..e46889a 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 ba51cc0..3a37508 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 d1575e2..1f78655 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 5998790..6386abd 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 a9ea2f6..27b13ad 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 d147ee0..596aecc 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -2123,6 +2123,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