aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>1999-07-30 21:34:44 +0000
committerRichard Henderson <rth@redhat.com>1999-07-30 21:34:44 +0000
commit587ff49e9a50b61e86ea78ba3271f3ca24c1b0e8 (patch)
treec5de899ca7fe15148721af69c6bae1b9f03810ea
parentd512aa072eb56b1fb1a5f1649b8c52a140901916 (diff)
downloadfsf-binutils-gdb-587ff49e9a50b61e86ea78ba3271f3ca24c1b0e8.zip
fsf-binutils-gdb-587ff49e9a50b61e86ea78ba3271f3ca24c1b0e8.tar.gz
fsf-binutils-gdb-587ff49e9a50b61e86ea78ba3271f3ca24c1b0e8.tar.bz2
Jakub Jelinek <jj@ultra.linux.cz>
* elf-bfd.h (struct elf_backend_data): Add print_symbol_all and output_arch_syms backend methods. * elfxx-target.h: Likewise. * elf64-sparc.c (sparc64_elf_bfd_link_hash_table_create, sparc64_elf_add_symbol_hook, sparc64_elf_output_arch_syms, sparc64_elf_get_symbol_type, sparc64_elf_symbol_processing): New functions. (sparc64_elf_size_dynamic_sections): Leave space for STT_REGISTER symbols in .dynsym, add their names into .dynstr. Put those symbols into dynlocal. (sparc64_elf_finish_dynamic_sections): Fix up DT_SPARC_REGISTER pointers to STT_REGISTER symbols in dynsym section. (sparc64_elf_print_symbol_all): New function. * elf.c (bfd_elf_print_symbol): Allow special backend symbol printing using the print_symbol_all hook.
-rw-r--r--bfd/ChangeLog18
-rw-r--r--bfd/elf-bfd.h15
-rw-r--r--bfd/elf.c17
-rw-r--r--bfd/elf64-sparc.c374
-rw-r--r--bfd/elflink.h44
-rw-r--r--bfd/elfxx-target.h8
6 files changed, 463 insertions, 13 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 5ca7ca4..a6ce276 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,21 @@
+1999-07-30 Jakub Jelinek <jj@ultra.linux.cz>
+
+ * elf-bfd.h (struct elf_backend_data): Add
+ print_symbol_all and output_arch_syms backend methods.
+ * elfxx-target.h: Likewise.
+ * elf64-sparc.c (sparc64_elf_bfd_link_hash_table_create,
+ sparc64_elf_add_symbol_hook, sparc64_elf_output_arch_syms,
+ sparc64_elf_get_symbol_type, sparc64_elf_symbol_processing): New
+ functions.
+ (sparc64_elf_size_dynamic_sections): Leave space for STT_REGISTER
+ symbols in .dynsym, add their names into .dynstr. Put those symbols
+ into dynlocal.
+ (sparc64_elf_finish_dynamic_sections): Fix up DT_SPARC_REGISTER
+ pointers to STT_REGISTER symbols in dynsym section.
+ (sparc64_elf_print_symbol_all): New function.
+ * elf.c (bfd_elf_print_symbol): Allow special backend symbol
+ printing using the print_symbol_all hook.
+
1999-07-30 Catherine Moore <clm@cygnus.com>
* elf32-arm.h (elf32_arm_check_relocs): Use r_offset for
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 577823b..3fa2513 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -581,6 +581,21 @@ struct elf_backend_data
void (*elf_backend_post_process_headers)
PARAMS ((bfd *, struct bfd_link_info *));
+ /* This function, if defined, prints a symbol to file and returns the
+ name of the symbol to be printed. It should return NULL to fall
+ back to default symbol printing. */
+ const char *(*elf_backend_print_symbol_all)
+ PARAMS ((bfd *, PTR, asymbol *));
+
+ /* This function, if defined, is called after all local symbols and
+ global symbols converted to locals are emited into the symtab
+ section. It allows the backend to emit special global symbols
+ not handled in the hash table. */
+ boolean (*elf_backend_output_arch_syms)
+ PARAMS ((bfd *, struct bfd_link_info *, PTR,
+ boolean (*) PARAMS ((PTR, const char *,
+ Elf_Internal_Sym *, asection *))));
+
/* The swapping table to use when dealing with ECOFF information.
Used for the MIPS ELF .mdebug section. */
const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap;
diff --git a/bfd/elf.c b/bfd/elf.c
index 9291b98..997408c 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -758,8 +758,21 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
case bfd_print_symbol_all:
{
CONST char *section_name;
+ CONST char *name = NULL;
+ struct elf_backend_data *bed;
+
section_name = symbol->section ? symbol->section->name : "(*none*)";
- bfd_print_symbol_vandf ((PTR) file, symbol);
+
+ bed = get_elf_backend_data (abfd);
+ if (bed->elf_backend_print_symbol_all)
+ name = (*bed->elf_backend_print_symbol_all) (abfd, filep, symbol);
+
+ if (name == NULL)
+ {
+ name = symbol->name;
+ bfd_print_symbol_vandf ((PTR) file, symbol);
+ }
+
fprintf (file, " %s\t", section_name);
/* Print the "other" value for a symbol. For common symbols,
we've already printed the size; now print the alignment.
@@ -827,7 +840,7 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
((unsigned int)
((elf_symbol_type *) symbol)->internal_elf_sym.st_other));
- fprintf (file, " %s", symbol->name);
+ fprintf (file, " %s", name);
}
break;
}
diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c
index 255713e..107f371 100644
--- a/bfd/elf64-sparc.c
+++ b/bfd/elf64-sparc.c
@@ -32,6 +32,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */
#define MINUS_ONE (~ (bfd_vma) 0)
+static struct bfd_link_hash_table * sparc64_elf_bfd_link_hash_table_create
+ PARAMS((bfd *));
static reloc_howto_type *sparc64_elf_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
static void sparc64_elf_info_to_howto
@@ -51,6 +53,13 @@ static boolean sparc64_elf_adjust_dynamic_symbol
PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
static boolean sparc64_elf_size_dynamic_sections
PARAMS((bfd *, struct bfd_link_info *));
+static int sparc64_elf_get_symbol_type
+ PARAMS (( Elf_Internal_Sym *, int));
+static boolean sparc64_elf_add_symbol_hook
+ PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+ const char **, flagword *, asection **, bfd_vma *));
+static void sparc64_elf_symbol_processing
+ PARAMS ((bfd *, asymbol *));
static boolean sparc64_elf_merge_private_bfd_data
PARAMS ((bfd *, bfd *));
@@ -596,6 +605,52 @@ sparc64_elf_write_relocs (abfd, sec, data)
}
}
+/* Sparc64 ELF linker hash table. */
+
+struct sparc64_elf_app_reg
+{
+ unsigned char bind;
+ unsigned short shndx;
+ bfd *abfd;
+ char *name;
+};
+
+struct sparc64_elf_link_hash_table
+{
+ struct elf_link_hash_table root;
+
+ struct sparc64_elf_app_reg app_regs [4];
+};
+
+/* Get the Sparc64 ELF linker hash table from a link_info structure. */
+
+#define sparc64_elf_hash_table(p) \
+ ((struct sparc64_elf_link_hash_table *) ((p)->hash))
+
+/* Create a Sparc64 ELF linker hash table. */
+
+static struct bfd_link_hash_table *
+sparc64_elf_bfd_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct sparc64_elf_link_hash_table *ret;
+
+ ret = ((struct sparc64_elf_link_hash_table *)
+ bfd_zalloc (abfd, sizeof (struct sparc64_elf_link_hash_table)));
+ if (ret == (struct sparc64_elf_link_hash_table *) NULL)
+ return NULL;
+
+ if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
+ _bfd_elf_link_hash_newfunc))
+ {
+ bfd_release (abfd, ret);
+ return NULL;
+ }
+
+ return &ret->root.root;
+}
+
+
/* Utility for performing the standard initial work of an instruction
relocation.
*PRELOCATION will contain the relocated item.
@@ -1196,6 +1251,221 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs)
return true;
}
+/* Hook called by the linker routine which adds symbols from an object
+ file. We use it for STT_REGISTER symbols. */
+
+static boolean
+sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ const Elf_Internal_Sym *sym;
+ const char **namep;
+ flagword *flagsp;
+ asection **secp;
+ bfd_vma *valp;
+{
+ static char *stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
+
+ if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
+ {
+ int reg;
+ struct sparc64_elf_app_reg *p;
+
+ reg = (int)sym->st_value;
+ switch (reg & ~1)
+ {
+ case 2: reg -= 2; break;
+ case 6: reg -= 4; break;
+ default:
+ (*_bfd_error_handler)
+ (_("%s: Only registers %%g[2367] can be declared using STT_REGISTER"),
+ bfd_get_filename (abfd));
+ return false;
+ }
+
+ if (info->hash->creator != abfd->xvec
+ || (abfd->flags & DYNAMIC) != 0)
+ {
+ /* STT_REGISTER only works when linking an elf64_sparc object.
+ If STT_REGISTER comes from a dynamic object, don't put it into
+ the output bfd. The dynamic linker will recheck it. */
+ *namep = NULL;
+ return true;
+ }
+
+ p = sparc64_elf_hash_table(info)->app_regs + reg;
+
+ if (p->name != NULL && strcmp (p->name, *namep))
+ {
+ (*_bfd_error_handler)
+ (_("Register %%g%d used incompatibly: "
+ "previously declared in %s to %s, in %s redefined to %s"),
+ (int)sym->st_value,
+ bfd_get_filename (p->abfd), *p->name ? p->name : "#scratch",
+ bfd_get_filename (abfd), **namep ? *namep : "#scratch");
+ return false;
+ }
+
+ if (p->name == NULL)
+ {
+ if (**namep)
+ {
+ struct elf_link_hash_entry *h;
+
+ h = (struct elf_link_hash_entry *)
+ bfd_link_hash_lookup (info->hash, *namep, false, false, false);
+
+ if (h != NULL)
+ {
+ unsigned char type = h->type;
+
+ if (type > STT_FUNC) type = 0;
+ (*_bfd_error_handler)
+ (_("Symbol `%s' has differing types: "
+ "previously %s, REGISTER in %s"),
+ *namep, stt_types [type], bfd_get_filename (abfd));
+ return false;
+ }
+
+ p->name = bfd_hash_allocate (&info->hash->table,
+ strlen (*namep) + 1);
+ if (!p->name)
+ return false;
+
+ strcpy (p->name, *namep);
+ }
+ else
+ p->name = "";
+ p->bind = ELF_ST_BIND (sym->st_info);
+ p->abfd = abfd;
+ p->shndx = sym->st_shndx;
+ }
+ else
+ {
+ if (p->bind == STB_WEAK
+ && ELF_ST_BIND (sym->st_info) == STB_GLOBAL)
+ {
+ p->bind = STB_GLOBAL;
+ p->abfd = abfd;
+ }
+ }
+ *namep = NULL;
+ return true;
+ }
+ else if (! *namep || ! **namep)
+ return true;
+ else
+ {
+ int i;
+ struct sparc64_elf_app_reg *p;
+
+ p = sparc64_elf_hash_table(info)->app_regs;
+ for (i = 0; i < 4; i++, p++)
+ if (p->name != NULL && ! strcmp (p->name, *namep))
+ {
+ unsigned char type = ELF_ST_TYPE (sym->st_info);
+
+ if (type > STT_FUNC) type = 0;
+ (*_bfd_error_handler)
+ (_("Symbol `%s' has differing types: "
+ "REGISTER in %s, %s in %s"),
+ *namep, bfd_get_filename (p->abfd), stt_types [type],
+ bfd_get_filename (abfd));
+ return false;
+ }
+ }
+ return true;
+}
+
+/* This function takes care of emiting STT_REGISTER symbols
+ which we cannot easily keep in the symbol hash table. */
+
+static boolean
+sparc64_elf_output_arch_syms (output_bfd, info, finfo, func)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ PTR finfo;
+ boolean (*func) PARAMS ((PTR, const char *,
+ Elf_Internal_Sym *, asection *));
+{
+ int reg;
+ struct sparc64_elf_app_reg *app_regs =
+ sparc64_elf_hash_table(info)->app_regs;
+ Elf_Internal_Sym sym;
+
+ /* We arranged in size_dynamic_sections to put the STT_REGISTER entries
+ at the end of the dynlocal list, so they came at the end of the local
+ symbols in the symtab. Except that they aren't STB_LOCAL, so we need
+ to back up symtab->sh_info. */
+ if (elf_hash_table (info)->dynlocal)
+ {
+ struct elf_link_local_dynamic_entry *e;
+
+ for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+ if (e->input_indx == -1)
+ break;
+ if (e)
+ {
+ elf_section_data (dynsymsec->output_section)->this_hdr.sh_info
+ = e->dynindx;
+ }
+ }
+
+ if (info->strip == strip_all)
+ return true;
+
+ for (reg = 0; reg < 4; reg++)
+ if (app_regs [reg].name != NULL)
+ {
+ if (info->strip == strip_some
+ && bfd_hash_lookup (info->keep_hash,
+ app_regs [reg].name,
+ false, false) == NULL)
+ continue;
+
+ sym.st_value = reg < 2 ? reg + 2 : reg + 4;
+ sym.st_size = 0;
+ sym.st_other = 0;
+ sym.st_info = ELF_ST_INFO (app_regs [reg].bind, STT_REGISTER);
+ sym.st_shndx = app_regs [reg].shndx;
+ if (! (*func) (finfo, app_regs [reg].name, &sym,
+ sym.st_shndx == SHN_ABS
+ ? bfd_abs_section_ptr : bfd_und_section_ptr))
+ return false;
+ }
+
+ return true;
+}
+
+static int
+sparc64_elf_get_symbol_type (elf_sym, type)
+ Elf_Internal_Sym * elf_sym;
+ int type;
+{
+ if (ELF_ST_TYPE (elf_sym->st_info) == STT_REGISTER)
+ return STT_REGISTER;
+ else
+ return type;
+}
+
+/* A STB_GLOBAL,STT_REGISTER symbol should be BSF_GLOBAL
+ even in SHN_UNDEF section. */
+
+static void
+sparc64_elf_symbol_processing (abfd, asym)
+ bfd *abfd;
+ asymbol *asym;
+{
+ elf_symbol_type *elfsym;
+
+ elfsym = (elf_symbol_type *) asym;
+ if (elfsym->internal_elf_sym.st_info
+ == ELF_ST_INFO (STB_GLOBAL, STT_REGISTER))
+ {
+ asym->flags |= BSF_GLOBAL;
+ }
+}
+
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
@@ -1495,6 +1765,11 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
must add the entries now so that we get the correct size for
the .dynamic section. The DT_DEBUG entry is filled in by the
dynamic linker and used by the debugger. */
+ int reg;
+ struct sparc64_elf_app_reg * app_regs;
+ struct bfd_strtab_hash *dynstr;
+ struct elf_link_hash_table *eht = elf_hash_table (info);
+
if (! info->shared)
{
if (! bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0))
@@ -1521,6 +1796,53 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
return false;
}
+
+ /* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER
+ entries if needed. */
+ app_regs = sparc64_elf_hash_table (info)->app_regs;
+ dynstr = eht->dynstr;
+
+ for (reg = 0; reg < 4; reg++)
+ if (app_regs [reg].name != NULL)
+ {
+ struct elf_link_local_dynamic_entry *entry, *e;
+
+ if (! bfd_elf64_add_dynamic_entry (info, DT_SPARC_REGISTER, 0))
+ return false;
+
+ entry = (struct elf_link_local_dynamic_entry *)
+ bfd_hash_allocate (&info->hash->table, sizeof (*entry));
+ if (entry == NULL)
+ return false;
+
+ /* We cheat here a little bit: the symbol will not be local, so we
+ put it at the end of the dynlocal linked list. We will fix it
+ later on, as we have to fix other fields anyway. */
+ entry->isym.st_value = reg < 2 ? reg + 2 : reg + 4;
+ entry->isym.st_size = 0;
+ if (*app_regs [reg].name != '\0')
+ entry->isym.st_name
+ = _bfd_stringtab_add (dynstr, app_regs[reg].name, true, false);
+ else
+ entry->isym.st_name = 0;
+ entry->isym.st_other = 0;
+ entry->isym.st_info = ELF_ST_INFO (app_regs [reg].bind,
+ STT_REGISTER);
+ entry->isym.st_shndx = app_regs [reg].shndx;
+ entry->next = NULL;
+ entry->input_bfd = output_bfd;
+ entry->input_indx = -1;
+
+ if (eht->dynlocal == NULL)
+ eht->dynlocal = entry;
+ else
+ {
+ for (e = eht->dynlocal; e->next; e = e->next)
+ ;
+ e->next = entry;
+ }
+ eht->dynsymcount++;
+ }
}
return true;
@@ -2346,6 +2668,7 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info)
struct bfd_link_info *info;
{
bfd *dynobj;
+ int stt_regidx = -1;
asection *sdyn;
asection *sgot;
@@ -2376,6 +2699,17 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info)
case DT_PLTGOT: name = ".plt"; size = false; break;
case DT_PLTRELSZ: name = ".rela.plt"; size = true; break;
case DT_JMPREL: name = ".rela.plt"; size = false; break;
+ case DT_SPARC_REGISTER:
+ if (stt_regidx == -1)
+ {
+ stt_regidx =
+ _bfd_elf_link_lookup_local_dynindx (info, output_bfd, -1);
+ if (stt_regidx == -1)
+ return false;
+ }
+ dyn.d_un.d_val = stt_regidx++;
+ bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
+ /* fallthrough */
default: name = NULL; size = false; break;
}
@@ -2505,7 +2839,34 @@ sparc64_elf_merge_private_bfd_data (ibfd, obfd)
}
return true;
}
+
+/* Print a STT_REGISTER symbol to file FILE. */
+static const char *
+sparc64_elf_print_symbol_all (abfd, filep, symbol)
+ bfd *abfd;
+ PTR filep;
+ asymbol *symbol;
+{
+ FILE *file = (FILE *) filep;
+ int reg, type;
+
+ if (ELF_ST_TYPE (((elf_symbol_type *) symbol)->internal_elf_sym.st_info)
+ != STT_REGISTER)
+ return NULL;
+
+ reg = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value;
+ type = symbol->flags;
+ fprintf (file, "REG_%c%c%11s%c%c R", "GOLI" [reg / 8], '0' + (reg & 7), "",
+ ((type & BSF_LOCAL)
+ ? (type & BSF_GLOBAL) ? '!' : 'l'
+ : (type & BSF_GLOBAL) ? 'g' : ' '),
+ (type & BSF_WEAK) ? 'w' : ' ');
+ if (symbol->name == NULL || symbol->name [0] == '\0')
+ return "#scratch";
+ else
+ return symbol->name;
+}
/* Set the right machine number for a SPARC64 ELF file. */
@@ -2570,6 +2931,9 @@ const struct elf_size_info sparc64_elf_size_info =
/* This is the value that we used before the ABI was released. */
#define ELF_MACHINE_ALT1 EM_OLD_SPARCV9
+#define bfd_elf64_bfd_link_hash_table_create \
+ sparc64_elf_bfd_link_hash_table_create
+
#define elf_info_to_howto \
sparc64_elf_info_to_howto
#define bfd_elf64_get_reloc_upper_bound \
@@ -2583,6 +2947,12 @@ const struct elf_size_info sparc64_elf_size_info =
#define elf_backend_create_dynamic_sections \
_bfd_elf_create_dynamic_sections
+#define elf_backend_add_symbol_hook \
+ sparc64_elf_add_symbol_hook
+#define elf_backend_get_symbol_type \
+ sparc64_elf_get_symbol_type
+#define elf_backend_symbol_processing \
+ sparc64_elf_symbol_processing
#define elf_backend_check_relocs \
sparc64_elf_check_relocs
#define elf_backend_adjust_dynamic_symbol \
@@ -2595,6 +2965,10 @@ const struct elf_size_info sparc64_elf_size_info =
sparc64_elf_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
sparc64_elf_finish_dynamic_sections
+#define elf_backend_print_symbol_all \
+ sparc64_elf_print_symbol_all
+#define elf_backend_output_arch_syms \
+ sparc64_elf_output_arch_syms
#define bfd_elf64_bfd_merge_private_bfd_data \
sparc64_elf_merge_private_bfd_data
diff --git a/bfd/elflink.h b/bfd/elflink.h
index 6fb9bba..cfb4909 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -2116,6 +2116,10 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
entry->input_indx = input_indx;
eht->dynsymcount++;
+ /* Whatever binding the symbol had before, it's now local. */
+ entry->isym.st_info
+ = ELF_ST_INFO (STB_LOCAL, ELF_ST_TYPE (entry->isym.st_info));
+
/* The dynindx will be set at the end of size_dynamic_sections. */
return true;
@@ -4253,16 +4257,22 @@ elf_bfd_final_link (abfd, info)
the original st_name with the dynstr_index. */
sym.st_name = e->isym.st_name;
- /* Whatever binding the symbol had before, it's now local. */
- sym.st_info = ELF_ST_INFO (STB_LOCAL,
- ELF_ST_TYPE (e->isym.st_info));
-
- s = bfd_section_from_elf_index (e->input_bfd, e->isym.st_shndx);
-
- sym.st_shndx = elf_section_data (s->output_section)->this_idx;
- sym.st_value = (s->output_section->vma
- + s->output_offset
- + e->isym.st_value);
+ if (e->isym.st_shndx == 0 || e->isym.st_shndx >= SHN_LORESERVE)
+ {
+ sym.st_shndx = e->isym.st_shndx;
+ sym.st_value = e->isym.st_value;
+ }
+ else
+ {
+ s = bfd_section_from_elf_index (e->input_bfd,
+ e->isym.st_shndx);
+
+ sym.st_shndx =
+ elf_section_data (s->output_section)->this_idx;
+ sym.st_value = (s->output_section->vma
+ + s->output_offset
+ + e->isym.st_value);
+ }
if (last_local < e->dynindx)
last_local = e->dynindx;
@@ -4272,7 +4282,7 @@ elf_bfd_final_link (abfd, info)
}
elf_section_data (finfo.dynsym_sec->output_section)
- ->this_hdr.sh_info = last_local;
+ ->this_hdr.sh_info = last_local + 1;
}
/* We get the global symbols from the hash table. */
@@ -4284,6 +4294,18 @@ elf_bfd_final_link (abfd, info)
if (eoinfo.failed)
return false;
+ /* If backend needs to output some symbols not present in the hash
+ table, do it now. */
+ if (bed->elf_backend_output_arch_syms)
+ {
+ if (! (*bed->elf_backend_output_arch_syms)
+ (abfd, info, (PTR) &finfo,
+ (boolean (*) PARAMS ((PTR, const char *,
+ Elf_Internal_Sym *, asection *)))
+ elf_link_output_sym))
+ return false;
+ }
+
/* Flush all symbols to the file. */
if (! elf_link_flush_output_syms (&finfo))
return false;
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index d40a870..3a787a2 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -297,6 +297,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef elf_backend_post_process_headers
#define elf_backend_post_process_headers NULL
#endif
+#ifndef elf_backend_print_symbol_all
+#define elf_backend_print_symbol_all NULL
+#endif
+#ifndef elf_backend_output_arch_syms
+#define elf_backend_output_arch_syms NULL
+#endif
/* Previously, backends could only use SHT_REL or SHT_RELA relocation
sections, but not both. They defined USE_REL to indicate SHT_REL
@@ -369,6 +375,8 @@ static CONST struct elf_backend_data elfNN_bed =
elf_backend_gc_mark_hook,
elf_backend_gc_sweep_hook,
elf_backend_post_process_headers,
+ elf_backend_print_symbol_all,
+ elf_backend_output_arch_syms,
elf_backend_ecoff_debug_swap,
ELF_MACHINE_ALT1,
ELF_MACHINE_ALT2,