-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* ldemul.c -- clearing house for ld emulation states
+ Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002, 2003, 2005
+ Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
GLD 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 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
any later version.
GLD is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GLD; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/*
- * $Id$
- */
-
-/*
- * clearing house for ld emulation states
- */
+along with GLD; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+#include "config.h"
#include "bfd.h"
#include "sysdep.h"
+#include "getopt.h"
+#include "bfdlink.h"
-#include "config.h"
#include "ld.h"
-#include "ldemul.h"
#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+#include "ldmain.h"
+#include "ldemul-list.h"
-extern ld_emulation_xfer_type ld_lnk960_emulation;
-extern ld_emulation_xfer_type ld_gldm88kbcs_emulation;
-extern ld_emulation_xfer_type ld_gld_emulation;
-extern ld_emulation_xfer_type ld_vanilla_emulation;
-extern ld_emulation_xfer_type ld_gld68k_emulation;
-extern ld_emulation_xfer_type ld_gld960_emulation;
-extern ld_emulation_xfer_type ld_gld29k_emulation;
-extern ld_emulation_xfer_type ld_gldnews_emulation;
-extern ld_emulation_xfer_type ld_h8300hds_emulation;
+static ld_emulation_xfer_type *ld_emulation;
+void
+ldemul_hll (char *name)
+{
+ ld_emulation->hll (name);
+}
-ld_emulation_xfer_type *ld_emulation;
+void
+ldemul_syslib (char *name)
+{
+ ld_emulation->syslib (name);
+}
void
-ldemul_hll(name)
-char *name;
+ldemul_after_parse (void)
{
- ld_emulation->hll(name);
+ ld_emulation->after_parse ();
}
+void
+ldemul_before_parse (void)
+{
+ ld_emulation->before_parse ();
+}
-void ldemul_syslib(name)
-char *name;
+void
+ldemul_after_open (void)
{
- ld_emulation->syslib(name);
+ ld_emulation->after_open ();
}
void
-ldemul_after_parse()
+ldemul_after_allocation (void)
{
- ld_emulation->after_parse();
+ ld_emulation->after_allocation ();
}
void
-ldemul_before_parse()
+ldemul_before_allocation (void)
{
- ld_emulation->before_parse();
+ ld_emulation->before_allocation ();
}
-void
-ldemul_after_allocation()
+void
+ldemul_set_output_arch (void)
{
- ld_emulation->after_allocation();
+ ld_emulation->set_output_arch ();
}
-void
-ldemul_before_allocation()
+void
+ldemul_finish (void)
{
- if (ld_emulation->before_allocation) {
- ld_emulation->before_allocation();
- }
+ if (ld_emulation->finish)
+ ld_emulation->finish ();
}
+void
+ldemul_set_symbols (void)
+{
+ if (ld_emulation->set_symbols)
+ ld_emulation->set_symbols ();
+}
void
-ldemul_set_output_arch()
+ldemul_create_output_section_statements (void)
{
- ld_emulation->set_output_arch();
+ if (ld_emulation->create_output_section_statements)
+ ld_emulation->create_output_section_statements ();
}
char *
-ldemul_choose_target()
+ldemul_get_script (int *isfile)
+{
+ return ld_emulation->get_script (isfile);
+}
+
+bfd_boolean
+ldemul_open_dynamic_archive (const char *arch, search_dirs_type *search,
+ lang_input_statement_type *entry)
+{
+ if (ld_emulation->open_dynamic_archive)
+ return (*ld_emulation->open_dynamic_archive) (arch, search, entry);
+ return FALSE;
+}
+
+bfd_boolean
+ldemul_place_orphan (lang_input_statement_type *file, asection *s)
+{
+ if (ld_emulation->place_orphan)
+ return (*ld_emulation->place_orphan) (file, s);
+ return FALSE;
+}
+
+void
+ldemul_add_options (int ns, char **shortopts, int nl,
+ struct option **longopts, int nrl,
+ struct option **really_longopts)
+{
+ if (ld_emulation->add_options)
+ (*ld_emulation->add_options) (ns, shortopts, nl, longopts,
+ nrl, really_longopts);
+}
+
+bfd_boolean
+ldemul_handle_option (int optc)
+{
+ if (ld_emulation->handle_option)
+ return (*ld_emulation->handle_option) (optc);
+ return FALSE;
+}
+
+bfd_boolean
+ldemul_parse_args (int argc, char **argv)
+{
+ /* Try and use the emulation parser if there is one. */
+ if (ld_emulation->parse_args)
+ return (*ld_emulation->parse_args) (argc, argv);
+ return FALSE;
+}
+
+/* Let the emulation code handle an unrecognized file. */
+
+bfd_boolean
+ldemul_unrecognized_file (lang_input_statement_type *entry)
{
- return ld_emulation->choose_target();
+ if (ld_emulation->unrecognized_file)
+ return (*ld_emulation->unrecognized_file) (entry);
+ return FALSE;
+}
+
+/* Let the emulation code handle a recognized file. */
+
+bfd_boolean
+ldemul_recognized_file (lang_input_statement_type *entry)
+{
+ if (ld_emulation->recognized_file)
+ return (*ld_emulation->recognized_file) (entry);
+ return FALSE;
}
char *
-ldemul_get_script()
-{
- return ld_emulation->get_script();
-}
-
-void
-ldemul_choose_mode(target)
-char *target;
-{
- if (strcmp(target,LNK960_EMULATION_NAME)==0) {
- ld_emulation = &ld_lnk960_emulation;
- }
- else if (strcmp(target,GLD960_EMULATION_NAME)==0) {
- ld_emulation = &ld_gld960_emulation;
- }
- else if (strcmp(target,GLDM88KBCS_EMULATION_NAME)==0) {
- ld_emulation = &ld_gldm88kbcs_emulation;
- }
-#ifndef GNU960
- else if (strcmp(target,GLD_EMULATION_NAME)==0) {
- ld_emulation = &ld_gld_emulation;
- }
- else if (strcmp(target,VANILLA_EMULATION_NAME)==0) {
- ld_emulation = &ld_vanilla_emulation;
- }
- else if (strcmp(target,H8300HDS_EMULATION_NAME)==0) {
- ld_emulation = &ld_h8300hds_emulation;
- }
-
- else if (strcmp(target,GLD68K_EMULATION_NAME)==0) {
- ld_emulation = &ld_gld68k_emulation;
- }
- else if (strcmp(target,GLD29K_EMULATION_NAME)==0) {
- ld_emulation = &ld_gld29k_emulation;
- }
- else if (strcmp(target,GLDNEWS_EMULATION_NAME)==0) {
- ld_emulation = &ld_gldnews_emulation;
- }
-#endif
- else {
- info("%P%F unrecognised emulation mode: %s\n",target);
- }
+ldemul_choose_target (int argc, char **argv)
+{
+ return ld_emulation->choose_target (argc, argv);
}
+/* The default choose_target function. */
+char *
+ldemul_default_target (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+{
+ char *from_outside = getenv (TARGET_ENVIRON);
+ if (from_outside != (char *) NULL)
+ return from_outside;
+ return ld_emulation->target_name;
+}
+
+void
+after_parse_default (void)
+{
+}
+
+void
+after_open_default (void)
+{
+}
+
+void
+after_allocation_default (void)
+{
+}
+
+void
+before_allocation_default (void)
+{
+ if (!link_info.relocatable)
+ strip_excluded_output_sections ();
+}
+
+void
+set_output_arch_default (void)
+{
+ /* Set the output architecture and machine if possible. */
+ bfd_set_arch_mach (output_bfd,
+ ldfile_output_architecture, ldfile_output_machine);
+}
+
+void
+syslib_default (char *ignore ATTRIBUTE_UNUSED)
+{
+ info_msg (_("%S SYSLIB ignored\n"));
+}
+
+void
+hll_default (char *ignore ATTRIBUTE_UNUSED)
+{
+ info_msg (_("%S HLL ignored\n"));
+}
+
+ld_emulation_xfer_type *ld_emulations[] = { EMULATION_LIST };
+
+void
+ldemul_choose_mode (char *target)
+{
+ ld_emulation_xfer_type **eptr = ld_emulations;
+ /* Ignore "gld" prefix. */
+ if (target[0] == 'g' && target[1] == 'l' && target[2] == 'd')
+ target += 3;
+ for (; *eptr; eptr++)
+ {
+ if (strcmp (target, (*eptr)->emulation_name) == 0)
+ {
+ ld_emulation = *eptr;
+ return;
+ }
+ }
+ einfo (_("%P: unrecognised emulation mode: %s\n"), target);
+ einfo (_("Supported emulations: "));
+ ldemul_list_emulations (stderr);
+ einfo ("%F\n");
+}
+
+void
+ldemul_list_emulations (FILE *f)
+{
+ ld_emulation_xfer_type **eptr = ld_emulations;
+ bfd_boolean first = TRUE;
+
+ for (; *eptr; eptr++)
+ {
+ if (first)
+ first = FALSE;
+ else
+ fprintf (f, " ");
+ fprintf (f, "%s", (*eptr)->emulation_name);
+ }
+}
+
+void
+ldemul_list_emulation_options (FILE *f)
+{
+ ld_emulation_xfer_type **eptr;
+ int options_found = 0;
+
+ for (eptr = ld_emulations; *eptr; eptr++)
+ {
+ ld_emulation_xfer_type *emul = *eptr;
+
+ if (emul->list_options)
+ {
+ fprintf (f, "%s: \n", emul->emulation_name);
+
+ emul->list_options (f);
+
+ options_found = 1;
+ }
+ }
+
+ if (! options_found)
+ fprintf (f, _(" no emulation specific options.\n"));
+}
+
+int
+ldemul_find_potential_libraries (char *name, lang_input_statement_type *entry)
+{
+ if (ld_emulation->find_potential_libraries)
+ return ld_emulation->find_potential_libraries (name, entry);
+
+ return 0;
+}
+
+struct bfd_elf_version_expr *
+ldemul_new_vers_pattern (struct bfd_elf_version_expr *entry)
+{
+ if (ld_emulation->new_vers_pattern)
+ entry = (*ld_emulation->new_vers_pattern) (entry);
+ return entry;
+}