--- /dev/null
+/* ld-emul.h - Linker emulation header file
+ Copyright 1991, 92, 93, 94, 95, 96, 97, 1998 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)
+ any later version.
+
+ GLD 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. */
+
+#ifndef LDEMUL_H
+#define LDEMUL_H
+
+#if ANSI_PROTOTYPES
+struct lang_input_statement_struct;
+struct search_dirs;
+#endif
+
+extern void ldemul_hll PARAMS ((char *));
+extern void ldemul_syslib PARAMS ((char *));
+extern void ldemul_after_parse PARAMS ((void));
+extern void ldemul_before_parse PARAMS ((void));
+extern void ldemul_after_open PARAMS ((void));
+extern void ldemul_after_allocation PARAMS ((void));
+extern void ldemul_before_allocation PARAMS ((void));
+extern void ldemul_set_output_arch PARAMS ((void));
+extern char *ldemul_choose_target PARAMS ((void));
+extern void ldemul_choose_mode PARAMS ((char *));
+extern void ldemul_list_emulations PARAMS ((FILE *));
+extern void ldemul_list_emulation_options PARAMS ((FILE *));
+extern char *ldemul_get_script PARAMS ((int *isfile));
+extern void ldemul_finish PARAMS ((void));
+extern void ldemul_set_symbols PARAMS ((void));
+extern void ldemul_create_output_section_statements PARAMS ((void));
+extern boolean ldemul_place_orphan
+ PARAMS ((struct lang_input_statement_struct *, asection *));
+extern int ldemul_parse_args PARAMS ((int, char **));
+extern boolean ldemul_unrecognized_file
+ PARAMS ((struct lang_input_statement_struct *));
+extern boolean ldemul_open_dynamic_archive
+ PARAMS ((const char *, struct search_dirs *,
+ struct lang_input_statement_struct *));
+extern char *ldemul_default_target PARAMS ((void));
+extern void after_parse_default PARAMS ((void));
+extern void after_open_default PARAMS ((void));
+extern void after_allocation_default PARAMS ((void));
+extern void before_allocation_default PARAMS ((void));
+extern void set_output_arch_default PARAMS ((void));
+extern void syslib_default PARAMS ((char*));
+extern void hll_default PARAMS ((char*));
+
+typedef struct ld_emulation_xfer_struct
+{
+ /* Run before parsing the command line and script file.
+ Set the architecture, maybe other things. */
+ void (*before_parse) PARAMS ((void));
+
+ /* Handle the SYSLIB (low level library) script command. */
+ void (*syslib) PARAMS ((char *));
+
+ /* Handle the HLL (high level library) script command. */
+ void (*hll) PARAMS ((char *));
+
+ /* Run after parsing the command line and script file. */
+ void (*after_parse) PARAMS ((void));
+
+ /* Run after opening all input files, and loading the symbols. */
+ void (*after_open) PARAMS ((void));
+
+ /* Run after allocating output sections. */
+ void (*after_allocation) PARAMS ( (void));
+
+ /* Set the output architecture and machine if possible. */
+ void (*set_output_arch) PARAMS ((void));
+
+ /* Decide which target name to use. */
+ char * (*choose_target) PARAMS ((void));
+
+ /* Run before allocating output sections. */
+ void (*before_allocation) PARAMS ((void));
+
+ /* Return the appropriate linker script. */
+ char * (*get_script) PARAMS ((int *isfile));
+
+ /* The name of this emulation. */
+ char *emulation_name;
+
+ /* The output format. */
+ char *target_name;
+
+ /* Run after assigning values from the script. */
+ void (*finish) PARAMS ((void));
+
+ /* Create any output sections needed by the target. */
+ void (*create_output_section_statements) PARAMS ((void));
+
+ /* Try to open a dynamic library. ARCH is an architecture name, and
+ is normally the empty string. ENTRY is the lang_input_statement
+ that should be opened. */
+ boolean (*open_dynamic_archive)
+ PARAMS ((const char *arch, struct search_dirs *,
+ struct lang_input_statement_struct *entry));
+
+ /* Place an orphan section. Return true if it was placed, false if
+ the default action should be taken. This field may be NULL, in
+ which case the default action will always be taken. */
+ boolean (*place_orphan)
+ PARAMS ((struct lang_input_statement_struct *, asection *));
+
+ /* Run after assigning parsing with the args, but before
+ reading the script. Used to initialize symbols used in the script. */
+ void (*set_symbols) PARAMS ((void));
+
+ /* Run to parse args which the base linker doesn't
+ understand. Return non zero on sucess. */
+ int (*parse_args) PARAMS ((int, char **));
+
+ /* Run to handle files which are not recognized as object files or
+ archives. Return true if the file was handled. */
+ boolean (*unrecognized_file)
+ PARAMS ((struct lang_input_statement_struct *));
+
+ /* Run to list the command line options which parse_args handles. */
+ void (* list_options) PARAMS ((FILE *));
+
+ /* Run to specially handle files which *are* recognized as object
+ files or archives. Return true if the file was handled. */
+ boolean (*recognized_file)
+ PARAMS ((struct lang_input_statement_struct *));
+
+} ld_emulation_xfer_type;
+
+typedef enum
+{
+ intel_ic960_ld_mode_enum,
+ default_mode_enum ,
+ intel_gld960_ld_mode_enum
+} lang_emulation_mode_enum_type;
+
+extern ld_emulation_xfer_type *ld_emulations[];
+
+#endif
PARAMS ((lang_wild_statement_type *, const char *, const char *));
static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *));
static void lang_gc_sections PARAMS ((void));
+static void lang_do_version_exports_section PARAMS ((void));
/* EXPORTS */
return;
}
+ if (ldemul_recognized_file (entry))
+ return;
+
/* We don't call ldlang_add_file for an archive. Instead, the
add_symbols entry point will call ldlang_add_file, via the
add_archive_element callback, for each element of the archive
case lang_constructors_statement_enum:
if (constructor_list.head != NULL)
{
- minfo (" CONSTRUCTORS\n");
+ if (constructors_sorted)
+ minfo (" SORT (CONSTRUCTORS)\n");
+ else
+ minfo (" CONSTRUCTORS\n");
print_statement_list (constructor_list.head, os);
}
break;
case lang_group_statement_enum:
lang_gc_sections_1 (s->group_statement.children.head);
break;
+ default:
+ break;
}
}
}
Handle the entry symbol at the same time. */
fake_list_start.next = ldlang_undef_chain_list_head;
- fake_list_start.name = entry_symbol;
+ fake_list_start.name = (char *) entry_symbol;
for (ulist = &fake_list_start; ulist; ulist = ulist->next)
{
link. */
lang_check ();
+ /* Handle .exports instead of a version script if we're told to do so. */
+ if (command_line.version_exports_section)
+ lang_do_version_exports_section ();
+
/* Build all sets based on the information gathered from the input
files. */
ldctor_build_sets ();
relax_again = false;
+ /* Note: pe-dll.c does something like this also. If you find
+ you need to change this code, you probably need to change
+ pe-dll.c also. DJ */
+
/* Do all the assignments with our current guesses as to
section sizes. */
lang_do_assignments (statement_list.head,
p->output_vma = 0;
}
-void
+lang_assignment_statement_type *
lang_add_assignment (exp)
etree_type * exp;
{
stat_ptr);
new->exp = exp;
+ return new;
}
void
return ret;
}
+
+static void
+lang_do_version_exports_section ()
+{
+ struct bfd_elf_version_expr *greg = NULL, *lreg;
+
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ asection *sec = bfd_get_section_by_name (is->the_bfd, ".exports");
+ char *contents, *p;
+ bfd_size_type len;
+
+ if (sec == NULL)
+ continue;
+
+ len = bfd_section_size (is->the_bfd, sec);
+ contents = xmalloc (len);
+ if (!bfd_get_section_contents (is->the_bfd, sec, contents, 0, len))
+ einfo (_("%X%P: unable to read .exports section contents"), sec);
+
+ while (p < contents+len)
+ {
+ greg = lang_new_vers_regex (greg, p);
+ p = strchr (p, '\0') + 1;
+ }
+
+ free (contents);
+
+ /* Do not include this section in the link. */
+ bfd_set_section_flags (is->the_bfd, sec,
+ bfd_get_section_flags (is->the_bfd, sec) | SEC_EXCLUDE);
+ }
+
+ lreg = lang_new_vers_regex (NULL, "*");
+ lang_register_vers_node (command_line.version_exports_section,
+ lang_new_vers_node (greg, lreg), NULL);
+}